2008年7月23日 星期三

資料結構操作及運算-圖形的Mask遮罩實作

Mask(遮罩),在影像處理裡面是很重要的功能,何謂Mask呢,它是利用被任何特定的演算法處理過所產生的黑白圖片,也就是二值化圖片(Thresholding),通常這些被處理過後的黑白圖片都有特地目的,例如擷取圖形物件(車牌,移動物體,膚色偵測)或是圖形去背,或是一些影像最佳化處理,利用這些黑白的圖片跟原始圖片做對應,白色255的部份為顯示出來的區域,黑色為0的部份為不顯示出來的區域,也就是將黑白影像具現化,白色的部份還原成圖片,在OpenCV裡面有很多可以支援Mask功能的函式,以下簡單介紹最基本的一個.

cvCopy()遮罩的使用
#include <cv.h>
#include <highgui.h>
#include <stdio.h>


int main()
{
    IplImage *Image1,*Image2,*MaskImage;
    Image1=cvLoadImage("grotto.jpg",1);

    CvSize Size1=cvGetSize(Image1);
    Image2=cvCreateImage(Size1,IPL_DEPTH_8U,3);
    cvSet(Image2,cvScalar(255,255,255));

    MaskImage=cvLoadImage("grotto_Threshold.jpg",0);

    cvCopy(Image1,Image2,MaskImage);

    cvNamedWindow("Image Mask",1);
    cvShowImage("Image Mask",Image2);
    cvNamedWindow("Thresholding Mask",1);
    cvShowImage("Thresholding Mask",MaskImage);

    cvWaitKey(0);
}

原始圖片:

(grotto.jpg)(grotto_Threshold.jpg)

執行結果:


一般最簡單的遮罩實作,就是這個啦,直接將黑白圖跟原始圖片做對應,不做任何動作,這張圖最大的缺點是含有許多雜訊,去除雜訊的方法會在後面演算法的部份提到.

上面的程式碼一開始讀取了原始圖片,創造了一個全白的圖RGB為(255,255,255),在讀取二值化圖形,接著,就用cvCopy()來做對應,因此,就跟上一篇的比較運算產生了一個簡單的演算法流程,在這邊除了cvCopy()可以做遮罩以外,還有以下列表

cvCopy()
cvSet()
cvAdd()
cvAddS()
cvSub()
cvSubS()
cvSubRS()
cvAnd()
cvAndS()
cvOr()
cvXor()
cvXorS()

全部都被包在"cxcore.h",但要注意的是,Mask遮罩的使用Mask這張圖必須要用單通道uchar型別的圖形結構,且一定要跟原始圖片同大小,而且,一定要用黑白圖,雖然OpenCV對Mask的規定是0與非0正整數,但是,這不是一般標準規格,在使用的時候建議以0跟255為基準.

影像處理演算法流程圖




6 意見:

匿名 提到...

請問我現在在一張圖上利用cvCircle畫了一個圈圈,然後我想把圈圈裡的圖像內容保存起來,不知道該怎麼做,感覺好像可以利用mask,但是第3個參數就不知道該丟什麼進去了,感謝您的撥空回答~

yester 提到...

您好
最近太忙了

cvCircle的連結

只要將圖二值化後用丟8bits單通道實心圓就可以了

程式碼範例如下:
#include <cv.h>
#include <highgui.h>

IplImage *Image1;

CvPoint CircleCenter;
int Radius;
CvScalar Color;
int Thickness;
int Shift;

int main()
{
    CvSize ImageSize1 = cvSize(1000,700);
    Image1 = cvCreateImage(ImageSize1,IPL_DEPTH_8U,1);
    cvNot(Image1,Image1);
    CircleCenter=cvPoint(500,350);
    Radius=300;
    Color=CV_RGB(0,0,0);
    Thickness=CV_FILLED;

    cvCircle(Image1,CircleCenter,Radius,Color,Thickness,CV_AA,Shift);

    cvNamedWindow("Circle",1);
    cvShowImage("Circle",Image1);
    cvWaitKey(0);
}

把Thickness放-1或是CV_FILLED就可以用實心圓,如果有何不解可以來問我^^

匿名 提到...

請問您文章提到的雜訊去除,不知道是怎麼做的呢?

yester 提到...

中通濾波器
或是connected component
侵蝕及膨脹
應該方法很多種
我只想到這幾種^^"

匿名 提到...

请问如果是在一张图上画了个矩形,矩形有倾斜角度,感觉应该也可以用mask,如何方便地把这个矩形里的图象内容保存出来呢?

匿名 提到...

Thx dude, the idea works like a charm :)

Copyright 2008-2009,yester