C++ 中利用 Opencv 得到不規則的ROI 區域(已知不規則區域)


因為需要,之前寫了一個利用mask 得到不規則ROI 區域的程序。
現在需要修改,發現自己都看不懂是怎么做的了。。
所以把它整理下來。


首先利用 鼠標可以得到 你想要的不規則區域的 頂點信息。具體這里不再描述。
setMouseCallback("setROIParking_Image", on_MouseHandle, (void*)&SrcImage);
得到不規則區域的頂點之后之后,接下來生成mask.
具體程序如下

    void Image::GetROImage()
     {
        Mat srcImage = imread(srcImageName);
        for (int j = 0; j < ROInumber; j++)
        {
	        Point root_points[1][4];
	        root_points[0][0] = DrawPoints[j*4];
	        root_points[0][1] = DrawPoints[j*4 + 1];
	        root_points[0][2] = DrawPoints[j*4 + 2];
	        root_points[0][3] = DrawPoints[j*4 + 3];

	        const Point* ppt[1] = { root_points[0] };
	        int npt[] = { 4 };
                //	polylines(srcImage, ppt, npt, 1, 1, Scalar(0, 0, 0), 1, 8, 0);

	        vector <Mat>mv;
	        cv::Mat mask_ann, dst,dst1,dst2;
	        srcImage.copyTo(mask_ann);
	        mask_ann.setTo(cv::Scalar::all(0));
	        fillPoly(mask_ann, ppt, npt, 1, Scalar(255, 255, 255));
	        split(mask_ann, mv);
	        srcImage.copyTo(dst, mv[0]);
	        vector<Point> rectPoints = {}; //得到rectangle 的角點
	        rectPoints.push_back(DrawPoints[j * 4]);
	        rectPoints.push_back(DrawPoints[j * 4 +1]);
	        rectPoints.push_back(DrawPoints[j * 4 +2]);
	        rectPoints.push_back(DrawPoints[j * 4 +3]);
        	Rect rec =  boundingRect(Mat(rectPoints));
	        dst1 = dst(rec); //boundingRect(Mat(rectPoints))  //得到rectROImage
	        if (dst1.cols >= 160) 
	        {
		        resize(dst1, dst2, Size(160, 120),0,0,3); //得到rectROImage_resize  //降采樣
	        }
	        else
	        {
		        resize(dst1, dst2, Size(160, 120),0,0,1);//放大
	        }
	         //默認為線性插值  INTER_NEAREST = 0(最近鄰插值), 
	        //INTER_LINEAR = 1(線性插值,默認值),
	        //INTER_CUBIC = 2(三次樣條插值),INTER_AREA  = 3(區域插值);INTER_LANCZOS4 = 4(Lanczos插值),
	         //INTER_MAX = 7, WARP_FILL_OUTLIERS = 8,
	           //降采樣:3, 放大:2(效率不高,不推薦);1(效率高,推薦)
	            imwrite(ROImageNames[j], dst);
	            imwrite(rectROImageNames[j], dst1);
	            imwrite(rectROImageNames_resize[j], dst2);
	            imwrite(rectROImageNames_resize_[j], dst2);
            }
    }

我這里寫的可能有些冗余,主要自己有點的也不是太懂,就根據自己的需要一點點添加得到自己想要的效果。

其中,DrawPoints里存儲了不規則區域的頂點(我這里設定了是不規則四邊形)。首先是 生成mask(我這里是mask_ann),

             srcImage.copyTo(mask_ann);
    	 mask_ann.setTo(cv::Scalar::all(0));

這一部分是生成和原圖一樣大小的mask 圖像,然后將整個圖像用黑色填充。

         const Point* ppt[1] = { root_points[0] };
         int npt[] = { 4 };
        fillPoly(mask_ann, ppt, npt, 1, Scalar(255, 255, 255));

這一部分是在mask 圖像中將不規則區域的部分用白色填充,參考:http://blog.csdn.net/billbliss/article/details/43968291 可以看一下效果

    vector <Mat>mv;
split(mask_ann, mv);
srcImage.copyTo(dst, mv[0]);

我添加的這一部分代碼,是跟通道分離有關,具體 也不是特別清楚。但是在我沒有添加這一句時,最后得到的圖像 有問題(會得到一個不規則ROI區域,但是不是自己想要的那一部分)。split 函數是將mask_ann的三個通道分別賦值給 mv . 因為這里的 mask_ann 是三通道的,而且三通道應該是一樣的,我們后面利用mask得到想要的不規則區域時只用到的他的一個通道。mv[0] 即它的一個通道。

后面的

        srcImage.copyTo(dst, mv[0]); 

即得到想要的不規則區域。即除了不規則區域,其他區域全部為黑色。

    Rect rec =  boundingRect(Mat(rectPoints));
dst1 = dst(rec); //boundingRect(Mat(rectPoints))  //得到rectROImage

是我從上面得到的部分中進一步的裁剪,把多余的黑色去掉,提取出了以 ROI 區域為邊界的的圖片(規則四邊形,周圍區域用黑色填充,因為如果ROI區域太小,得到的圖片中大部分都是黑色,所以進一步裁剪)。

因為我想得到最終 尺寸一樣的圖像,所以利用resize進行了 升降采樣。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM