1. 将图像ROI区域利用copyTo复制到一张和原图相同大小的纯黑图片上并且位置与原图一致,这样进行处理后就可以直接将处理坐标用于原图上
- 然而如博客所述处理后最外层轮廓被保留而这不是我们想要的
- 查看findContours函数其中第三个参数mode可以设置轮廓检索模式
void cv::findContours (
InputArray image,
OutputArrayOfArrays contours,
OutputArray hierarchy,
int mode,
int method,
Point offset = Point()
)
- mode可选参数如下:
参数 | 含义 |
---|---|
RETR_EXTERNAL | 只保留最外层轮廓,对于所有轮廓有hierarchy[i][2]=hierarchy[i][3]=-1 |
RETR_LIST | 检索所有轮廓且不为他们建立层次关系 |
RETR_CCOMP | 获取所有轮廓并且为他们建立一个两层的层次关系,最外层轮廓为顶级,第二层次为孔洞的边界,如果在孔洞里还有其他连通区域的轮廓则它也被置于顶层 |
RETR_TREE | 获取所有轮廓并且为他们建立完整嵌套层次关系 |
RETR_TREE |
hierarchy [Next, Previous, First_Child, Parent]
hierarchy[i][0]~hierarchy[i][3]
分别表示 后一个轮廓,前一个轮廓,内嵌子轮廓,父轮廓的索引编号,如果没有父轮廓或子轮廓则该值为-1- 当时想着刚好不要最外层轮廓也不需要包含在目标内的轮廓,刚好使用RETR_CCOMP不要顶层轮廓只取第二层轮廓就刚好是想要的结果,那么只需要取存在父轮廓的第二层轮廓即
hierarchy[i][2]!=-1
即可,下面是当时设置了findContours(bin, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE, Point(0, 0));
后hierarchy的参数结果
第 0 个轮廓 1 , -1 , -1 , -1
第 1 个轮廓 2 , 0 , -1 , -1
第 2 个轮廓 3 , 1 , -1 , -1
第 3 个轮廓 4 , 2 , -1 , -1
第 4 个轮廓 5 , 3 , -1 , -1
第 5 个轮廓 6 , 4 , -1 , -1
第 6 个轮廓 7 , 5 , -1 , -1
第 7 个轮廓 8 , 6 , -1 , -1
第 8 个轮廓 9 , 7 , -1 , -1
第 9 个轮廓 11 , 8 , 10 , -1
第 10 个轮廓 -1 , -1 , -1 , 9
第 11 个轮廓 12 , 9 , -1 , -1
第 12 个轮廓 13 , 11 , -1 , -1
第 13 个轮廓 14 , 12 , -1 , -1
第 14 个轮廓 15 , 13 , -1 , -1
第 15 个轮廓 16 , 14 , -1 , -1
第 16 个轮廓 17 , 15 , -1 , -1
第 17 个轮廓 18 , 16 , -1 , -1
第 18 个轮廓 19 , 17 , -1 , -1
第 19 个轮廓 20 , 18 , -1 , -1
第 20 个轮廓 21 , 19 , -1 , -1
第 21 个轮廓 22 , 20 , -1 , -1
第 22 个轮廓 23 , 21 , -1 , -1
第 23 个轮廓 24 , 22 , -1 , -1
第 24 个轮廓 25 , 23 , -1 , -1
第 25 个轮廓 26 , 24 , -1 , -1
第 26 个轮廓 27 , 25 , -1 , -1
第 27 个轮廓 28 , 26 , -1 , -1
第 28 个轮廓 29 , 27 , -1 , -1
第 29 个轮廓 30 , 28 , -1 , -1
第 30 个轮廓 31 , 29 , -1 , -1
第 31 个轮廓 32 , 30 , -1 , -1
第 32 个轮廓 -1 , 31 , -1 , -1
第 0 个轮廓 1 , -1 , -1 , -1
第 1 个轮廓 2 , 0 , -1 , -1
第 2 个轮廓 3 , 1 , -1 , -1
第 3 个轮廓 4 , 2 , -1 , -1
第 4 个轮廓 5 , 3 , -1 , -1
第 5 个轮廓 6 , 4 , -1 , -1
第 6 个轮廓 7 , 5 , -1 , -1
第 7 个轮廓 8 , 6 , -1 , -1
第 8 个轮廓 9 , 7 , -1 , -1
第 9 个轮廓 10 , 8 , -1 , -1
第 10 个轮廓 11 , 9 , -1 , -1
第 11 个轮廓 12 , 10 , -1 , -1
第 12 个轮廓 13 , 11 , -1 , -1
第 13 个轮廓 14 , 12 , -1 , -1
第 14 个轮廓 15 , 13 , -1 , -1
第 15 个轮廓 16 , 14 , -1 , -1
第 16 个轮廓 17 , 15 , -1 , -1
第 17 个轮廓 18 , 16 , -1 , -1
第 18 个轮廓 19 , 17 , -1 , -1
第 19 个轮廓 20 , 18 , -1 , -1
第 20 个轮廓 21 , 19 , -1 , -1
第 21 个轮廓 22 , 20 , -1 , -1
第 22 个轮廓 23 , 21 , -1 , -1
第 23 个轮廓 24 , 22 , -1 , -1
第 24 个轮廓 25 , 23 , -1 , -1
第 25 个轮廓 -1 , 24 , -1 , -1
- 然而取了hierarchy[i][2]!=-1后仍然会保留最外层轮廓
2. 将ROI区域提取出来映射回原图时设置偏移量
-
API
findContours()
和drawContours()
的最后一个参数Point offset = Point()
即是点的偏移量 -
在ROI上
findContours()
,不用设置偏移量即最后一个参数不填或者设置为Point(0, 0)
-
映射回原图时
drawContours()
的偏移量应为ROI区域左上角坐标在原图上的位置即为Point(boundRect[i].x, boundRect[i].y)
-
或者利用
rectangle
画外接矩形映射回原图时,在左上角右下角坐标上都加上(偏移量ROI区域左上角坐标在原图上的位置),这样就能将对应的矩形框映射到原图的对应位置
rectangle(srcImage,
Point(boundRect[i].x+boundRect1[i2].x, boundRect[i].y+boundRect1[i2].y),
Point(boundRect[i].x+boundRect1[i2].x+boundRect1[i2].width, boundRect[i].y+boundRect1[i2].y+boundRect1[i2].height),
Scalar(255,0,0), 2, 8, 0); //绘制第 i 个外接矩形
- 一开始循环内的参数忘记更改导致全都画在了底部,后来也是左上角右下角坐标设置出错导致框特别大,全部更正好后画的框就可以映射回原图了