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进行了 升降采样。

相关文章
相关标签/搜索