今天将opencv的霍夫变换修改并优化了一下,就是先预处理,切割、二值化、去噪之后进行霍夫变换,效果还不错,从识别70多个圆,慢慢修改到识别32个圆。
效果如下:
原理毛星云写的就很好,他的文章链接:https://blog.csdn.net/poem_qianmo/article/details/26977557
下面附上代码:
#include "stdafx.h"
#include "core/core.hpp"
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <set>
#include<stdio.h>
#include <opencv2/core.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/videoio.hpp>//for camera
#include <opencv2/video.hpp>
#include <opencv2/ml/ml.hpp>
#include "opencv2/ml/ml.hpp"
#include <time.h>
#include <ctime>
#include <string>
using namespace std;
using namespace cv;
//-----------------------------------【命名空间声明部分】---------------------------------------
// 描述:包含程序所使用的命名空间
//-----------------------------------------------------------------------------------------------
//-----------------------------------【main( )函数】--------------------------------------------
// 描述:控制台应用程序的入口函数,我们的程序从这里开始
//-----------------------------------------------------------------------------------------------
int main()
{
//【1】载入原始图和Mat变量定义
Mat srcImage = imread("3.jpg"); //工程目录下应该有一张名为1.jpg的素材图
Mat midImage, dstImage;//临时变量和目标图的定义
//【2】显示原始图
namedWindow("【原始图】", 0);//参数为零,则可以自由拖动
imshow("【原始图】", srcImage);
Rect rect(600, 0, 1205, 1035); //创建一个Rect框,属于cv中的类,四个参数代表x,y,width,height
Mat image_cut = Mat(srcImage, rect); //从img中按照rect进行切割,此时修改image_cut时image中对应部分也会修改,因此需要copy
Mat image_copy = image_cut.clone(); //clone函数创建新的图片
namedWindow("分割后的图片", 0);//参数为零,则可以自由拖动
imshow("分割后的图片", image_copy);
//【3】转为灰度图,进行图像平滑
cvtColor(image_copy, midImage, CV_BGR2GRAY);//灰度化
//二值化
threshold(midImage, midImage, 128, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
//使用3*3内核来降噪
blur(midImage, midImage, Size(3, 3));//进行模糊
//GaussianBlur(midImage, midImage, Size(9, 9), 2, 2);
//Rect rect(600,0, 1205, 1035); //创建一个Rect框,属于cv中的类,四个参数代表x,y,width,height
//Mat image_cut = Mat(midImage, rect); //从img中按照rect进行切割,此时修改image_cut时image中对应部分也会修改,因此需要copy
//Mat image_copy = image_cut.clone(); //clone函数创建新的图片
//namedWindow("分割后的图片", 0);//参数为零,则可以自由拖动
//imshow("分割后的图片", image_copy);
//【4】进行霍夫圆变换
vector<Vec3f> circles;
// HoughCircles(midImage, circles, CV_HOUGH_GRADIENT, 1.5, 10, 200, 100, 0, 0);
// 第五个参数 圆的圆心之间的最小距离
HoughCircles(midImage, circles, CV_HOUGH_GRADIENT, 1.5, 35, 100, 25, 36, 43);
//【5】依次在图中绘制出圆
for (size_t i = 0; i < circles.size(); i++)
{
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
cout << "圆心 " << i << "= " << center << ";\n" << endl;
cout << "半径= " << i << "= " << radius << ";\n" << endl;
//绘制圆心
circle(midImage, center, 3, Scalar(0, 255, 0), -1, 8, 0);
//绘制圆轮廓
circle(midImage, center, radius, Scalar(155, 50, 255), 3, 8, 0);
//绘制圆心
circle(image_copy, center, 3, Scalar(0, 255, 0), -1, 8, 0);
//绘制圆轮廓
circle(image_copy, center, radius, Scalar(155, 50, 255), 3, 8, 0);
}
cout << "共检测到圆" << circles.size() << " 个圆" << ";\n" << endl;
//【6】显示效果图
namedWindow("【二值化后效果图】", 0);//参数为零,则可以自由拖动
imshow("【二值化后效果图】", midImage);
namedWindow("【彩色效果图】", 0);//参数为零,则可以自由拖动
imshow("【彩色效果图】", image_copy);
waitKey(0);
return 0;
}