1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > 使用OpenCV实现Halcon算法(7)选择轮廓 select_shape

使用OpenCV实现Halcon算法(7)选择轮廓 select_shape

时间:2019-09-04 11:46:34

相关推荐

使用OpenCV实现Halcon算法(7)选择轮廓 select_shape

一、先看他人的文章

转载的网址是:

/jsxyhelu/p/4650151.html

halcon源码:

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中也要这样的结果,就需要自己动手尝试实现。实现过程中我采用了类似的函数名表示敬意。

24位图

// 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 );//带有上下限的thresholdvoid 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_shapevector<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_shapevector<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();}

8位图

//connectionstd::vector<std::vector<cv::Point>> connection(const cv::Mat& src, cv::Mat& draw){draw = cv::Mat::zeros(src.rows, src.cols, CV_8UC1);std::vector<std::vector<cv::Point>>contours;cv::findContours(src, contours, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE);for (int i = 0; i < contours.size(); i++){cv::drawContours(draw, contours, i, cv::Scalar(255));}return contours;}//select_shapestd::vector<std::vector<cv::Point>> selectShapeArea(const cv::Mat& src, cv::Mat& draw, const std::vector<std::vector<cv::Point>>& contours, int minvalue, int maxvalue){std::vector<std::vector<cv::Point>> result_contours;draw = Mat::zeros(src.rows, src.cols, CV_8UC1);for (int i = 0; i < contours.size(); i++){int countour_area = contourArea(contours[i]);if (countour_area > minvalue && countour_area < maxvalue){result_contours.emplace_back(contours[i]);}}for (int i = 0; i < result_contours.size(); i++){drawContours(draw, result_contours, i, cv::Scalar(255), -1);}return result_contours;}

二、再看我的原创

这里使用OpenCV自带的connectedComponentsWithStats算子,标记连通区域,然后根据面积来过滤想要的区域。

//连通,黑底白图,白色代表有数据,黑色代表没有数据cv::Mat matLabels, matStats, matCentroids;//centroids是质心int nccomps = cv::connectedComponentsWithStats(imageBinary, matLabels, matStats, matCentroids);//连通数目//面积过滤int left = 0;int top = 0;int width = 0;int height = 0;int connArea = 0;std::vector<cv::Rect> vtRect;std::vector<int> vtLabels;for (int i = 1; i < nccomps; i++) //i从1开始,因为0是黑色{left = matStats.at<int>(i, cv::CC_STAT_LEFT); //stats分别是L,T,W,H,Areatop = matStats.at<int>(i, cv::CC_STAT_TOP);width = matStats.at<int>(i, cv::CC_STAT_WIDTH);height = matStats.at<int>(i, cv::CC_STAT_HEIGHT);connArea = matStats.at<int>(i, cv::CC_STAT_AREA);if (connArea > 5000 && connArea < 999999999){vtRect.emplace_back(cv::Rect(left, top, width, height));vtLabels.emplace_back(i);}}cv::Mat imageSelected = Mat::zeros(imageBinary.rows, imageBinary.cols, CV_8UC1);int rowBegin = 0;int rowEnd = 0;int colBegin = 0;int colEnd = 0;int lbl = 0;for (int n = 0; n < vtLabels.size(); n++){rowBegin = vtRect[n].y;rowEnd = vtRect[n].y + vtRect[n].height;colBegin = vtRect[n].x;colEnd = vtRect[n].x + vtRect[n].width;for (int i = rowBegin; i <= rowEnd; i++)//row{uchar* uc_pixel = imageSelected.data + i * imageSelected.step;for (int k = colBegin; k <= colEnd; k++)//col{lbl = matLabels.at<int>(i, k);std::vector<int>::iterator result = std::find(vtLabels.begin(), vtLabels.end(), lbl); //查找1if (result == vtLabels.end()) //没找到{uc_pixel[k] = 0;}else //找到{uc_pixel[k] = 255;}}}}

---

参考文献

选择轮廓(select_shape)

选择轮廓(select_shape) - jsxyhelu - 博客园

opencv的实用研究--分析轮廓并寻找边界点

opencv的实用研究--分析轮廓并寻找边界点 - jsxyhelu - 博客园

如何识别出轮廓准确的长和宽

如何识别出轮廓准确的长和宽 - jsxyhelu - 博客园

OpenCV中的新函数connectedComponentsWithStats使用

OpenCV中的新函数connectedComponentsWithStats使用 - jsxyhelu - 博客园

OpenCV使用FindContours进行二维码定位

OpenCV使用FindContours进行二维码定位 - jsxyhelu - 博客园

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。