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

  • 相关阅读:
    EF 事务
    关于C#如何将Word转换成PDF的方法汇总
    莫德纳公司
    C# 填充pdf 模板生成报告
    自定义滚动条的样式
    Docker 大势已去,Podman 即将崛起……
    一款基于 Spring Boot 开发的 OA 项目,已开源,真香..
    当你运行npm run命令时,会发生什么?
    Java遇上SPL:架构优势和开发效率,一个不放过
    如何使用Python实现图像融合及加法运算?
  • 原文地址:https://www.cnblogs.com/lifeofershisui/p/7529993.html
Copyright © 2020-2023  润新知