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

由於須要,以前寫了一個利用mask 獲得不規則ROI 區域的程序。
如今須要修改,發現本身都看不懂是怎麼作的了。。
因此把它整理下來。函數


首先利用 鼠標能夠獲得 你想要的不規則區域的 頂點信息。具體這裏再也不描述。
setMouseCallback("setROIParking_Image", on_MouseHandle, (void*)&SrcImage);
獲得不規則區域的頂點以後以後,接下來生成mask.
具體程序以下.net

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);
            }
    }

我這裏寫的可能有些冗餘,主要本身有點的也不是太懂,就根據本身的須要一點點添加獲得本身想要的效果。code

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

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 能夠看一下效果get

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

我添加的這一部分代碼,是跟通道分離有關,具體 也不是特別清楚。可是在我沒有添加這一句時,最後獲得的圖像 有問題(會獲得一個不規則ROI區域,可是不是本身想要的那一部分)。split 函數是將mask_ann的三個通道分別賦值給 mv . 由於這裏的 mask_ann 是三通道的,並且三通道應該是同樣的,咱們後面利用mask獲得想要的不規則區域時只用到的他的一個通道。mv[0] 即它的一個通道。it

後面的class

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

即獲得想要的不規則區域。即除了不規則區域,其餘區域所有爲黑色。效率

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

是我從上面獲得的部分中進一步的裁剪,把多餘的黑色去掉,提取出了以 ROI 區域爲邊界的的圖片(規則四邊形,周圍區域用黑色填充,由於若是ROI區域過小,獲得的圖片中大部分都是黑色,因此進一步裁剪)。程序

由於我想獲得最終 尺寸同樣的圖像,因此利用resize進行了 升降採樣。

相關文章
相關標籤/搜索