有時候想要把一張影像去除背景,我都會開啟影像處理軟體,慢慢地用魔術棒把我要的部份的輪廓給圈出來,可是這樣子太過於麻煩,若背景只有單純的顏色,而我要的部份沒有那顏色,就可以顏色遮罩(Color Mask)來取得我要的部份。
這圖是我過濾某個範圍顏色後的效果,呈現黑色的部份就是被過濾掉的顏色囉~
結果圖(反)
程式碼非常簡單,我先產生五張影像,接著定義我要的顏色範圍,過濾到作為遮罩用影像。接著根據原始影像和遮罩影像拷貝到結果影像,我想看結果就很容易明白我在做什麼了~
/** Theme: Color Mask Compiler: Dev C++ 4.9.9.2 Library: OpenCV 2.0 Date: 102/05/09 Author: HappyMan Blog: https://cg2010studio.wordpress.com/ */ #include <highgui.h> #include <cv.h> int main() { IplImage *img = cvLoadImage("happyman.jpg"); IplImage *mask = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1); IplImage *mask_ = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1); IplImage *result = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 3); IplImage *result_ = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 3); cvInRangeS(img, cvScalar(0,0,0), cvScalar(100,100,100), mask); cvNot(mask, mask_); cvCopy(img, result, mask); cvCopy(img, result_, mask_); cvShowImage("HappyMan", img); cvShowImage("HappyMan Mask", mask); cvShowImage("HappyMan Mask_", mask_); cvShowImage("HappyMan Result", result); cvShowImage("HappyMan Result_", result_); cvWaitKey(0); return 0; }
原始圖
遮罩圖(正)
遮罩圖(反)
結果圖(正)
#關鍵函式:InRangeS
檢查陣列元素是否在兩個數量之間
void cvInRangeS( const CvArr* src, CvScalar lower, CvScalar upper, CvArr* dst );
- src
第一個原陣列 - lower
包括進的下邊界 - upper
不包括進的上邊界 - dst
輸出陣列必須是 8u 或 8s 類型
函數 cvInRangeS 檢查輸入陣列元素範圍:對於單通道陣列:
dst(I)=lower0 <= src(I)0 < upper0
對於雙通道陣列以此類推:
dst(I) = lower0 <= src(I)0 < upper0 && lower1 <= src(I)1 < upper1
如果 src(I) 在範圍內dst(I)被設置為 0xff (每一位都是 ‘1’)否則置0 。所有的陣列必須有相同的大小(或ROI大小)
#關鍵函式:cvcopy
拷貝一個陣列給另一個陣列
void cvCopy( const CvArr* src, CvArr* dst, const CvArr* mask=NULL );
- src
輸入陣列。 - dst
輸出陣列。 - mask
操作遮罩是8比特單通道的陣列,它指定了輸出陣列中被改變的元素。
函數cvCopy從輸入陣列中複製選定的成分到輸出陣列:
如果mask(I)!=0,則dst(I)=src(I)。
如果輸入輸出陣列中的一個是IplImage類型的話,其ROI和COI將被使用。輸入輸出陣列必須是同樣的類型、維數和大小。函數也可以用來複製散列陣列(這種情況下不支援mask)。
隨意留個言吧:)~