持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第33天,点击查看活动详情
python在进行图像处理时利用lambda表达式几行代码就可以搞定fincontours函数中找到的轮廓排序问题,而且可以根据调整坐标轴的维度实现不同的排序方式,具体的实现代码我放一下代码,方便与c++的实现方式进行比较。
python版
# 其中cnt没有什么实际含义,主要是作为一个key值,在对contours排序时会根据排序结果自动调整cnt的值,所以说非常方便
cnt = [1, 4, -1, 8, 0, 9, 2]
# 待排序的轮廓,这里为了方便展示,自己随便写的数值
contours = [(1, 2, 3, 4), (9, 10, 2, 2), (8, 7, 3, 1), (1, 3, 2, 5), (1, 1, 3, 4), (5, 6, 5, 4), (3, 4, 1, 2)]
# 排序函数,其中*sorted(),首先是一个key-value也就是zip(cnt, contours),lambda d:d[1][0],是按照key还是value进行排序
# d[1][0]中1表示按照value进行排序,如果是想按照key排序,把lambda改为d:d[0],因为key是一维数组,所以只需要d[0]即可
# d[1][0]后面的0表示按照value的第0列数据进行排序,也就是对应例子中[1,9,8,1,1,5,3]这一列,可以改为1,2,3列,最大到3,因为value只有四列。
(cnt, contours) = zip(*sorted(zip(cnt, contours), key=lambda d: d[1][0], reverse=False))
最后得到的是排序后的cnt和contours
c++的话相对麻烦一些,代码我已经写好了,是对contours按照坐标进行排序的函数,可以直接拿来用。代码如下
void Widget::sort_contours(vector<vector<Point> > contours)
{
vector<RotatedRect> box(contours.size());
for(int i=0;i<contours.size();i++)
{
box[i] = minAreaRect(contours[i]);
}
// 排序时也使用了lambda表达式的形式。
std::sort(box.begin(), box.end(), [](const RotatedRect& pt1, const RotatedRect& pt2){
Point2f rect1[4];
Point2f rect2[4];
pt1.points(rect1);
pt2.points(rect2);
if(rect1->x!=rect2->x)
return rect1->x<rect2->x;
else
return rect1->y<rect2->y;
});
int counts = 0;
Point2f rect[4];
for(int i=0;i<contours.size();i++)
{
box[i].points(rect);
for(int j=0; j<4; j++)
{
line(img1, rect[j], rect[(j+1)%4], Scalar(0, 0, 255), 1, 8); //绘制最小外接矩形每条边
}
putText(img1, to_string(counts), Point(rect->x, rect->y),FONT_HERSHEY_SIMPLEX,1,Scalar(255,255,0),1);
counts++;
}
imshow("sortedImg", img1);
waitKey(0);
}
没有排序之前
排序之后
现在在数据层面可以看到排序前后box的数据发生了变化,说明排序已经生效,由于此处还没有进行NMS抑制,所有效果看起来较差,会存在轮廓包含或者嵌套现象,下一篇博客将实现一下NMS算法,python已经实现,后面我会对c++的方法进行实现一下,并分享出来。