您的位置:首页 > 其它

[blog 算法原理]选择轮廓(select_shape)

2015-07-16 06:05 375 查看
选择轮廓(select_shape) Halcon是一款运用广泛的图像识别和处理软件。在肤浅的接触中,它的轮廓选择算子(select_shape)给予我很深的印象。结果是往往几行代码就能够产生很好的效果: 比如要得到这样的结果

只需要
read_image (Image1, 'F:/未来项目/钢管识别/FindTube/FindTube/1.jpg')
rgb1_to_gray (Image1, GrayImage)
threshold (GrayImage, Regions, 43, 111)
connection (Regions, ConnectedRegions)
select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 150, 666)
select_shape (SelectedRegions, SelectedRegions1, 'circularity', 'and', 0.45, 1)
当然Halcon是在背后做了许多工作的。 几行代码中,比较重要的是算子就是"select_shape"。这个算子的参数很多,我也就比较熟悉这两种。 如果我想在Opencv中也要这样的结果,就需要自己动手尝试实现。实现过程中我采用了类似的函数名表示敬意。

// selectshape.cpp : 选择轮廓
// by: jsxyhelu(1755311380)
#include "stdafx.h"
#include <iostream>
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace std;
using namespace cv;
#define  VP  vector<Point>  //用VP符号代替 vector<point>
RNG  rng(12345    );
//带有上下限的threshold
void threshold2(Mat gray,Mat& thresh,int minvalue,int maxvalue)
{
Mat thresh1;
Mat thresh2;
threshold(gray,thresh1,43,255, THRESH_BINARY);
threshold(gray,thresh2,111,255,THRESH_BINARY_INV);
thresh = thresh1 & thresh2;
}
//寻找并绘制出联通区域
vector<VP> connection2(Mat src,Mat& draw)
{
draw = Mat::zeros(src.rows,src.cols,CV_8UC3);
vector<VP>contours;
findContours(src,contours,CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE);
for (int i=0;i<contours.size();i++)
{
Scalar  color  = Scalar(rng.uniform(0,255),rng.uniform(0,255),rng.uniform(0,255));
drawContours(draw,contours,i,color,-1);
}
return contours;
}
//select_shape
vector<VP>  selectShapeArea(Mat src,Mat& draw,vector<VP> contours,int minvalue,int maxvalue)
{
vector<VP> result_contours;
draw = Mat::zeros(src.rows,src.cols,CV_8UC3);
for (int i=0;i<contours.size();i++)
{
int countour_area = contourArea(contours[i]);
if (countour_area >minvalue && countour_area<maxvalue)
{
result_contours.push_back(contours[i]);
}
}
for (int i=0;i<result_contours.size();i++)
{
Scalar  color  = Scalar(rng.uniform(0,255),rng.uniform(0,255),rng.uniform(0,255));
drawContours(draw,result_contours,i,color,-1);
}
return result_contours;
}
//计算轮廓的圆的特性
float calculateCircularity(VP contour)
{
Point2f center;
float radius = 0;
minEnclosingCircle((Mat)contour,center,radius);
//以最小外接圆半径作为数学期望,计算轮廓上各点到圆心距离的标准差
float fsum = 0;
float fcompare = 0;
for (int i=0;i<contour.size();i++)
{
Point2f ptmp = contour[i];
float fdistenct = sqrt((float)((ptmp.x - center.x)*(ptmp.x - center.x)+(ptmp.y - center.y)*(ptmp.y-center.y)));
float fdiff = abs(fdistenct - radius);
fsum = fsum + fdiff;
}
fcompare = fsum/(float)contour.size();
return fcompare;
}
//select_shape
vector<VP> selectShapeCircularity(Mat src,Mat& draw,vector<VP> contours,float minvalue,float maxvalue)
{
vector<VP> result_contours;
draw = Mat::zeros(src.rows,src.cols,CV_8UC3);
for (int i=0;i<contours.size();i++)
{
float fcompare = calculateCircularity(contours[i]);
if (fcompare >=minvalue && fcompare <=maxvalue)
{
result_contours.push_back(contours[i]);
}
}
for (int i=0;i<result_contours.size();i++)
{
Scalar  color  = Scalar(rng.uniform(0,255),rng.uniform(0,255),rng.uniform(0,255));
drawContours(draw,result_contours,i,color,-1);
}
return result_contours;
}
int _tmain(int argc, _TCHAR* argv[])
{
Mat src;
Mat gray;
Mat thresh;
Mat draw_connection;
Mat draw_area;
Mat draw_circle;
vector<VP>contours_connection;
vector<VP>contours_area;
vector<VP>contours_circle;
vector<VP>contours_tmp;
//read_image (Image1, 'F:/未来项目/钢管识别/FindTube/FindTube/1.jpg')
src = imread("1.jpg");
//rgb1_to_gray (Image1, GrayImage)
cvtColor(src,gray,COLOR_BGR2GRAY);
//threshold (GrayImage, Regions, 43, 111)
threshold2(gray,thresh,43,111);
//connection (Regions, ConnectedRegions)
contours_connection = connection2(thresh.clone(),draw_connection);
//select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 150, 666)
contours_area = selectShapeArea(thresh.clone(),draw_area,contours_connection,150,666);
//select_shape (SelectedRegions, SelectedRegions1, 'circularity', 'and', 0.45, 1)
contours_circle = selectShapeCircularity(thresh.clone(),draw_circle,contours_area,1,6);
//显示结果
imshow("src",src);
imshow("thresh",thresh);
imshow("draw_connection",draw_connection);
imshow("draw_area",draw_area);
imshow("draw_circle",draw_circle);
waitKey();
}

结果如下,这段代码中还有一个问题,就是计算轮廓圆的性质的方法,我这里采用的是自己想出来的方法,似乎不是很完善,需要进一步找到资料才修正。


来自为知笔记(Wiz)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: