首页 > 其他分享 >answerOpenCV轮廓类问题解析

answerOpenCV轮廓类问题解析

时间:2022-12-26 23:07:08浏览次数:54  
标签:解析 img int opencv bw contours answerOpenCV 轮廓 255

contour在opencv中是一个基础的数据结构,灵活运用的话,作用很大。以contour为关键字,在answerOpenCV中能够发现很多有趣的东西。



answerOpenCV轮廓类问题解析_ci



 



1、无法解决的问题



​http://answers.opencv.org/question/195718/how-to-remove-unwanted-areaspixels-from-image/​




answerOpenCV轮廓类问题解析_OpenCV_02


The problem is that. I just want to take the external contours of the main leaf in the image. Or If it is possible, The image can be cleaned. The second important point is that the process should be standard for all images.


解析:这个提问者希望从上面的叶子图片,得到叶子的轮廓。但实际上这是不可能完成的任务,这个图片质量达不到要求,关于这一点,是图像处理的常识。


也就是根本无法轮廓分析,因为没有稳定的轮廓。


 


2、如何从图像中获得完整轮廓


How to find dimensions of an object in the image


​http://answers.opencv.org/question/195807/how-to-find-dimensions-of-an-object-in-the-image/?answer=196027#post-id-196027​


 


这道题厉害了,一看这个需求就是专业的:


I want to find the length of an object in the image (image length not the real physical length). My first idea is was to use ​​boundingRect​​​ to find the dimensions, but some of the masks I have split in between them so the ​​​boundingRect​​ method fails. Can someone suggest me a robust method to find the length of the object in the given mask


 



answerOpenCV轮廓类问题解析_ci_03


他需要从这个图中活动轮廓的长度(这个应该是一个脚印),但是因为图上轮廓可能有多个,所以不知道怎么办。


解析: 这道题的关键, 就在于实际上,每张图的轮廓只有一个。 这是重要的先验条件。那怎么办?把识别出来的轮廓连起来呀。


连的方法有多种,我给出两种比较保险:


1、形态学变化



answerOpenCV轮廓类问题解析_ci_04


    dilate(bw,bw,Mat(11,11,CV_8UC1));



answerOpenCV轮廓类问题解析_i++_05


2、实在距离太远,靠不上了,直接把中线连起来吧



answerOpenCV轮廓类问题解析_ci_06


 


由于这道题目前还没有比较好的解决方法,所以我实现了一个,应该是可以用的,这是结果:



answerOpenCV轮廓类问题解析_ci_07


网站代码也已经提交到网站上了

//程序主要部分



int main( int argc, char** argv )



{



//读入图像,转换为灰度



Mat img = imread("e:/sandbox/1234.png");



Mat bw;



bool dRet;



cvtColor(img, bw, COLOR_BGR2GRAY);



//阈值处理



threshold(bw, bw, 150, 255, CV_THRESH_BINARY);



bitwise_not(bw,bw);



//形态学变化



dilate(bw,bw,Mat(11,11,CV_8UC1));



erode(bw,bw,Mat(11,11,CV_8UC1));



//寻找轮廓



vector<vector<Point> > contours;



vector<Vec4i> hierarchy;



findContours(bw, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);



/// 计算矩



vector<Moments> mu(contours.size() );



for( int i = 0; i < contours.size(); i++ )



mu[i] = moments( contours[i], false );



/// 计算中心矩:



vector<Point2f> mc( contours.size() );



for( int i = 0; i < contours.size(); i++ )



mc[i] = Point2f( mu[i].m10/mu[i].m00 , mu[i].m01/mu[i].m00 );



//connect all contours into ONE



for (int i = 0; i < contours.size(); ++i)



{



Scalar color = Scalar( rng12345.uniform(0, 255), rng12345.uniform(0,255), rng12345.uniform(0,255) );



drawContours( img, contours, i, color, 2, 8, hierarchy, 0, Point() );



circle( img, mc[i], 4, color, -1, 8, 0 );



//connect



if (i+1 <contours.size())



line(bw,mc[i],mc[i+1],Scalar(255,255,255));



}



contours.clear();



hierarchy.clear();



//寻找结果



findContours(bw, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);



for (int i = 0;i<contours.size();i++)



{



RotatedRect minRect = minAreaRect( Mat(contours[i]) );



Point2f rect_points[4];



minRect.points( rect_points );



for( int j = 0; j < 4; j++ )



line( img, rect_points[j], rect_points[(j+1)%4],Scalar(255,255,0),2);



float fshort = std::min(minRect.size.width,minRect.size.height); //short



float flong = std::max(minRect.size.width,minRect.size.height); //long



}



imshow("img",img);



waitKey();



return 0;



}


 


3、新函数


Orientation of two contours


​http://answers.opencv.org/question/113492/orientation-of-two-contours/​


 



answerOpenCV轮廓类问题解析_OpenCV_08


 


这个topic希望能够获得两个轮廓之间的角度。并且后期通过旋转将两者重合。


I try to calculate the orientation of 2 contours. At the end i want to rotate one contour, so it is in cover with the other one. With my code I get a result, but it isn't that accurate. Also I get the same orientations although the contours is rotated around 90 degrees.


 


解析: 如果是我,一定会直接使用pca分别求出两个轮廓的角度,然后算差。但是原文中使用了,并且提出了独特的解决方法。


 


Shape Distance and Common Interfaces


​​​ https://docs.opencv.org/3.0-beta/modules/shape/doc/shape_distances.html#shapecontextdistanceextractor​​ ​​


 


Shape Distance algorithms in OpenCV are derivated from a common interface that allows you toswitch between them in a practical way for solving the same problem with different methods.Thus, all objects that implement shape distance measures inherit the ​​ShapeDistanceExtractor​​ interface.


当然,有了这个函数,做轮廓匹配也是非常方便:



answerOpenCV轮廓类问题解析_i++_09


​​​ http://answers.opencv.org/question/28489/how-to-compare-two-contours-translated-from-one-another/​​ ​​


 


4、发现opencv的不足


I need a maxEnclosingCircle function


​http://answers.opencv.org/question/958/i-need-a-maxenclosingcircle-function/?answer=196029#post-id-196029​


 


opencv目前是没有最大内接圆函数的(当然它还没有很多函数),但是这个只有研究要一定程度的人才会发现。这里他提问了,我帮助解决下:


 



answerOpenCV轮廓类问题解析_OpenCV_10


 


 

#
include

"stdafx.h"


#
include

<
iostream
>




using

namespace
std;

using

namespace
cv;





VP FindBigestContour(Mat src){



int
imax
=

0
;
//代表最大轮廓的序号



int
imaxcontour
=

-
1
;
//代表最大轮廓的大小


std
:
:
vector
<
std
:
:
vector
<
cv
:
:
Point
>>
contours;


findContours(src,contours,CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE);



for
(
int
i
=
0
;i
<
contours.size();i
++
){



int
itmp
=
contourArea(contours[i]);
//这里采用的是轮廓大小



if
(imaxcontour
<
itmp ){


imax
=
i;


imaxcontour
=
itmp;


}


}



return
contours[imax];


}

int
main(
int
argc,
char
*
argv[])


{


Mat src
=
imread(
"e:/template/cloud.png"
);


Mat temp;


cvtColor(src,temp,COLOR_BGR2GRAY);


threshold(temp,temp,
100
,
255
,THRESH_OTSU);


imshow(
"src"
,temp);



//寻找最大轮廓


VP VPResult
=
FindBigestContour(temp);



//寻找最大内切圆



int
dist
=

0
;



int
maxdist
=

0
;


Point center;



for
(
int
i
=
0
;i
<
src.cols;i
++
)


{



for
(
int
j
=
0
;j
<
src.rows;j
++
)


{


dist
=
pointPolygonTest(VPResult,cv
:
:
Point(i,j),
true
);



if
(dist
>
maxdist)


{


maxdist
=
dist;


center
=
cv
:
:
Point(i,j);


}


}


}



//绘制结果


circle(src,center,maxdist,Scalar(
0
,
0
,
255
));


imshow(
"dst"
,src);


waitKey();


}

 


 


 


另过程中,发现了pyimagesearch上的一些不错文章,感谢这个blog的作者的长期、高质量的付出,向他学习。


1、 Removing contours from an image using Python and OpenCV


​https://www.pyimagesearch.com/2015/02/09/removing-contours-image-using-python-opencv/​


 


2、 Sorting Contours using Python and OpenCV


​https://www.pyimagesearch.com/2015/04/20/sorting-contours-using-python-and-opencv/​


 


3、 Finding extreme points in contours with OpenCV


​​​ https://www.pyimagesearch.com/2016/04/11/finding-extreme-points-in-contours-with-opencv/​​ ​​


 


结语:


实际上,最近我正在做关于轮廓的事情,这也是今天我做这个研究的直接原因。


 


我的问题是:如何识别出轮廓准确的长和宽


比如这张,其中2的这个外轮廓明显是识别错误的,这样它的长宽也是错误的(注意里面我标红的1和2)



answerOpenCV轮廓类问题解析_i++_11


 


代码:



int main( int argc, char** argv )



{



//read the image



Mat img = imread("e:/sandbox/leaf.jpg");



Mat bw;



bool dRet;



//resize



pyrDown(img,img);



pyrDown(img,img);







cvtColor(img, bw, COLOR_BGR2GRAY);



//morphology operation



threshold(bw, bw, 150, 255, CV_THRESH_BINARY);



//bitwise_not(bw,bw);



//find and draw contours



vector<vector<Point> > contours;



vector<Vec4i> hierarchy;



findContours(bw, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);



for (int i = 0;i<contours.size();i++)



{



RotatedRect minRect = minAreaRect( Mat(contours[i]) );



Point2f rect_points[4];



minRect.points( rect_points );



for( int j = 0; j < 4; j++ )



line( img, rect_points[j], rect_points[(j+1)%4],Scalar(255,255,0),2);



}



imshow("img",img);



waitKey();



return 0;



}


我们要得到这样的结果



answerOpenCV轮廓类问题解析_OpenCV_12


 


当然,这个代码我已经差不多写出来了,如何获得轮廓的真实的长宽?这个问题很实际,opencv没有实现,目前看来answeropencv也人问?


就是这张图片?想看看大家的想法。也可以直接在answeropencv上进行讨论。



answerOpenCV轮廓类问题解析_i++_13


 


answerOpencv的讨论地址为:


 


​http://answers.opencv.org/question/196032/how-to-find-the-real-width-and-height-of-contours/​


 


 


感谢阅读至此,希望有所帮助。


 


 


 


标签:解析,img,int,opencv,bw,contours,answerOpenCV,轮廓,255
From: https://blog.51cto.com/jsxyhelu2017/5971117

相关文章

  • python解析rosbag
      #coding:utf-8#!/usr/bin/python#Extractimagesfromabagfile.importsysimportosimportroslib#roslib.load_manifest(PKG)importrosbagimpo......
  • SQL解析调研
    概述在做大数据产品时,经常遇到的一个需求,页面上有一个输入框,可以输入SQL语句,然后获得执行结果。如adhoc。注:本文局限于Java语言。调研Druid阿里的Druid,开源作者推广时,称其为......
  • .NET中国开发者峰会11.9 下午分会场1 内容解析
    China.NETConf2019中国.NET开发者峰会即将在上海召开,这次大会是一届完全由社区组织举办的中国.NET开发者盛会,我们筹备大会之初就定下了大会的主题是“开源、共享、创......
  • 一文解析Spring JDBC Template的使用指导
    摘要:Spring框架对JDBC的简单封装。提供了一个JDBCTemplate对象简化JDBC的开发。本文分享自华为云社区《SpringJdbcTemplate使用解析》,作者:共饮一杯无。Spring框架对JD......
  • 爱奇艺:基于龙蜥与 Koordinator 在离线混部的实践解析 | 龙蜥技术
    在 ​​2022云栖大会龙蜥峰会云原生专场​​上,来自爱奇艺的基础架构研究员赵慰分享了《基于龙蜥与Koordinator的在离线混部实践》技术演讲,以下为本次演讲内容: 一、爱......
  • C++不知算法系列之解析回溯算法中的人文哲学
    1.前言回溯算法让我想起“退一步海阔天空”的名言。当事情的发展到了绝境或是边缘时,可以试着后退一步,换一个方向、换一种策略,或许会看到新的出路或生机。回溯算法的精髓:......
  • 什么时候需要查询DNS记录,如何查询DNS解析记录?
    当搭建一个新网站时,DNS查询工具对查询网站DNS解析记录方面很有帮助。除了在设置新网站时有用外,也会在更新DNS记录、设置邮件服务器等场景会使用到DNS查询工具。搭建新网站......
  • Sql Server 压缩数据库日志文件的方法解析
    SqlServer日志_log.ldf文件太大,数据库文件有500g,日志文件也达到了500g,占用磁盘空间过大,且可能影响程序性能,需要压缩日志文件,下面小编给大家讲解下SqlServer压缩数据......
  • win32-style类风格解析
     style类风格解析类风格含义  CS_VREDRAW移动或者调整窗口的高度(垂直方向)时,重绘整个窗口  CW_HREDRAW移动或者调整窗口的宽度(水平方向)时,重绘整个窗......
  • LongAdder类实现原理、源码解析
    1.概述AtomicLong通过循环CAS实现原子操作,缺点是当高并发下竞争比较激烈的时候,会出现大量的CAS失败,导致循环CAS次数大大增加,这种自旋是要消耗时间cpu时间片的,......