OpenCV截取ROI区域——多种形状

背景:在做一个中国象棋机器人的项目,项目中需要识别象棋棋子上的汉字,计划采用CNN的方式实现这一功能。在制作CNN训练的数据集的时候,需要一个截取象棋中心文字的问题。当我们定位到一个象棋的位置之后,我首先将包裹象棋的一个50*50的矩形取阈截取出来,但是,发现如果只是做矩形的截取的话,截取的图像仍然会包含一部分的棋盘,导致训练时的干扰,因此就考虑再做圆形的截取

语言:C++(Opencv3.4.1)

1、截取矩形的ROI:

1   /* cut off each piece */
2   Rect piece_ROI(Point(center.x-piece_roi_size/2,center.y-piece_roi_size/2),Point(center.x+piece_roi_size/2,center.y+piece_roi_size/2));
3   Mat piece_cutoff = piece_image(piece_ROI);

  

  可以看到,在截取一个矩形的时候,比较简单,可以直接定义一个Opencv中的Rect对象,输入需要截取的矩形区域的坐标即可

  这是大致的截取效果:
    

2、截取圆形的ROI:

  这里涉及到截取一个不是矩形的区域,不管是截取一个圆形、椭圆,或者是截取一个不规则多边形,其方法都是使用contour(轮廓)来指定ROI。

  比如,要截取一个多边形的ROI区域:

 1     Mat dst;
 2     Mat roi = Mat::zeros(img.size(),CV_8U);
 3 
 4     vector<vector<Point>> contour;
 5     vector<Point> pts;
 6     pts.push_back(Point(30,45));
 7     pts.push_back(Point(100,15));
 8     pts.push_back(Point(300,145));
 9     pts.push_back(Point(330,240));
10     pts.push_back(Point(50,250));
11     contour.push_back(pts);
12 
13     drawContours(roi,contour,0,Scalar::all(255),-1);
14     img.copyTo(dst,roi);
15 
16     imshow("roi",roi);
17     imshow("img",img);
18     imshow("dst",dst);

 

  如果要截取一个圆形区域,方法相似:

1     Mat dst = Mat::zeros(image.size(), image.type());
2     Mat mask = Mat::zeros(image.size(),CV_8U);
3 
4     Point circleCenter(mask.cols / 2, mask.rows / 2);
5     int radius = min(mask.cols, mask.rows)/2;
6     // 画圆
7     circle(mask, circleCenter, radius, Scalar(255),-1);
8 
9     image.copyTo(dst, mask);

  

  如果要截取一个椭圆呢?也是一样的方法:

1     ellipse(mask,circleCenter,Size(240,146),10,-180,180,Scalar(255),-1);

 

3、项目实例:

  在我的象棋机器人项目中,我用如下代码实现此功能(分为两步,因为两步的结果,我都需要),可供参考:

 1     /* cut off each piece */
 2     Rect piece_ROI(Point(center.x-piece_roi_size/2,center.y-piece_roi_size/2),Point(center.x+piece_roi_size/2,center.y+piece_roi_size/2));
 3     Mat piece_cutoff = piece_image(piece_ROI);
 4     Mat piece_save =   Mat::zeros(Size(piece_roi_size,piece_roi_size),CV_8UC3);
 5     static Mat piece_mask = Mat::zeros(Size(piece_roi_size,piece_roi_size),CV_8UC1);
 6     circle(piece_mask,Point(piece_roi_size/2,piece_roi_size/2),radius-3,Scalar(255),-1);
 7     piece_cutoff.copyTo(piece_save,piece_mask);
 8 
 9     /* show the piece roi to save */
10     //imshow("piece cutoff",piece_cutoff);
11     //imshow("piece mask",piece_mask);

  截取的效果如下:

    

 

 

4、copyTo函数

  官方手册说明:

    

 

   eg:

1     src.copyTo(dst, mask);

    说明:将 src 的位于 mask 中的部分,拷贝到 dst 中。这里,mask是一个“掩膜”, 其中非零的位置既是指定了 src 中的那些需要拷贝的部分。

 

posted @ 2021-03-29 13:09  Yu_tiann  阅读(3568)  评论(0编辑  收藏  举报