图像处理_Opencv的霍夫(Hough)圆检测定位、字符匹配、字符识别

我的图像处理课程的一个实验。

一.任务

识别字符:
在这里插入图片描述

二.使用平台

Windows10专业版
VS2015企业版
C++ opencv3.2

三.图像处理的思路

1.先定位感兴趣区域(字符区域)

定位有两种方法,一种是定位圆,另一种是定位直线
在这里插入图片描述

2.然后模版匹配(matchTemplate)

模版匹配需要做好模版。将感兴趣区域找出后,可以采用像素投影分割法,将每个字符分割出来保存到本地文件夹做样本。
在这里插入图片描述

四.图像处理

整个流程:
1.读入图像
2.转为灰度
3.中值滤波
4.固定阈值二值化。(因为我定位的是圆)
5.霍夫圆检测找到圆心
6.根据圆心剪裁感兴趣区域
7.读取本地文件夹样本
8.进行模版匹配
9.标出模板匹配结果

图像:

1.转为灰度中值滤波

灰度后中值滤波

2.二值化后霍夫圆检测

二值化、霍夫圆检测

3.根据圆心坐标裁出字符区域

感兴趣区域

3.模版匹配后标记结果

结果

代码:

#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
#include <string>
using namespace cv;
using namespace std;

Mat src, dst, gray, binImg;
Mat eImage;

int main(int argc, char** argv)
{
	src = imread("G:\\U_lesson\\图像处理\\实验\\zf1.bmp");

	if (src.empty())
	{
		printf("can not load image....\n");
		return -1;
	}
	// 窗口命名
	namedWindow("test", CV_WINDOW_AUTOSIZE);
	imshow("test", src);

	//中值滤波
	Mat moutput;
	medianBlur(src, moutput, 11);
	imshow("moutput", moutput);

	cvtColor(moutput, gray, CV_BGR2GRAY);

	// 固定阈值二值化
	threshold(gray, binImg, 15, 255, THRESH_BINARY);
	imshow("binImg", binImg);

	// 霍夫圆检测
	vector<Vec3f> pcircles;
	HoughCircles(binImg, pcircles, CV_HOUGH_GRADIENT, 1, 50, 15, 15, 25, 80);
	src.copyTo(dst);
    
    // 画圆与圆心
	for (size_t i = 0; i < pcircles.size(); i++)
	{
		Vec3f cc = pcircles[i];
		circle(dst, Point(cc[0], cc[1]), cc[2], Scalar(0, 0, 255), 2, LINE_AA);
		circle(dst, Point(cc[0], cc[1]), 2, Scalar(98, 23, 255), 2, LINE_AA);
		cout << cc << endl;
	}
	imshow("dst", dst);

	 // 简陋判断有无圆心坐标
	if (pcircles[0][0] > 0 && pcircles[0][1] > 0)
	{
		// 剪裁出字符区域
		int start_x = pcircles[0][0] - 280;
		int start_y = pcircles[0][1] + 80;
		int rect_width = 500;
		int rect_height = 140;
		Rect  rect(start_x, start_y, rect_width, rect_height);
		Mat ROI = src(rect);
		imshow("rect", ROI);

		Mat dst_gray, dst_bin;
		cvtColor(ROI, dst_gray, CV_BGR2GRAY);  

		int height = dst_gray.rows;
		int width = dst_gray.cols;

        // 取出本地文件的样本
		vector<Mat> character_image;
		char tempstr[12] = { '2','0','1','8','1','2','0','7','2','5','1','C'};
		for (int i = 0; i <= 11; i++)
		{
			string ImgName = "character";
			ImgName = ImgName + to_string(i);
			ImgName = "G:\\U_lesson\\图像处理\\实验\\match\\" + ImgName + ".bmp";
			Mat temp = imread(ImgName);
			character_image.push_back(temp);
		}
		
		Mat tmp_dst;
		Mat find_dst;
		dst_gray.copyTo(find_dst);
		cvtColor(find_dst, find_dst, CV_GRAY2BGR);
		// 模版匹配
		for (int i = 0; i <= 11; i++)
		{
			Mat temp;
			cvtColor(character_image[i],temp, CV_BGR2GRAY);

			width = dst_gray.cols - temp.cols + 1;
			height = dst_gray.rows - temp.rows + 1;
			Mat result(width, height, CV_32FC1);

			Point minLoc;
			Point maxLoc;
			double min, max;
			Point temLoc;

			dst_gray.copyTo(tmp_dst);
			matchTemplate(dst_gray, temp, result, CV_TM_CCORR_NORMED, Mat());

			// 找到匹配的最大最小坐标
			minMaxLoc(result, &min, &max, &minLoc, &maxLoc, Mat());
			temLoc = maxLoc;
			cout << temLoc << endl;
			
			// 画出矩形框
			rectangle(find_dst, Rect(temLoc.x, temLoc.y, temp.cols, temp.rows), Scalar(0, 0, 255), 2, 8);
			
			
			string str(1, tempstr[i]);
			putText(find_dst, str, Point(temLoc.x, temLoc.y), FONT_HERSHEY_COMPLEX, 1, cv::Scalar(0, 255, 0), 1, 8, 0);
			
			cout << tempstr[i] << endl;
			//rectangle(result, Rect(temLoc.x, temLoc.y, temp.cols, temp.rows), Scalar(0, 0, 255), 2, 8);
		}

		imshow("AAA", find_dst);

	}
	waitKey(0);
	return 0;
}

被抛弃的写随笔公众号改写技术文章了,感兴趣的可以关注公众号:王崇卫
在这里插入图片描述

  • 4
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
前言: 开源的opencv真是一件伟大的产品,那么多个函数跟变量(具体多少还没数过)。要是结合起来综合运用几乎可以胜任任何有关图像识别和处理方面的工作。如果能更深入一根据具体需要修改或优化里面的源码那更是如虎添翼。 花了时间浏览了www.opencv.org.cn论坛里的所有贴子,还好不多才200多页。总体上对opencv里的一些常用函数功能作用大致有了解,筛选一些跟元件识别有关的运用内容,但它论坛里的贴子回复的内容到即止的居多。从网上下载了能搜到的教程跟代码全学习了解测试了一下,图像处理流程通常先开始都是要进行滤波,除燥,灰度,二值化后再轮廓识别等。 开始动手 经过多次好多次运行测试组合,终于有一次显示出意外的惊人效果,而且相当简单只是调用了几个函数而以,就可以有这样效果实在出人意料。第一个是进行元件中心获取,也是直接调用函数再加东西就可以得出元件的四个矩形顶坐标,有这几个坐标就可以直接算出元件中间所在的坐标了。如果要检测元件摆放角度是否是垂直90度,只要判断边宽的长度为最小或最大时就是垂直90度。 但这个矩形框无法测出元件具体角度。如截图: 测试视频地址:https://v.youku.com/v_show/id_XMjU5NzY5NTI0.html 不过,还有另外一个函数可以提供这个功能,调用后可以直接求出最小外接矩形和角度 如截图: 测试视频地址:https://v.youku.com/v_show/id_XMjYwMDMzMDc2.html 说明:里面的光源不行,临时用手电筒,和在光盘上插几个LED做环形灯做照明,无法做到无阴影显示。如果光源做的好,效果应该是非常精确稳定。 识别包含下面2种做法: opencv里需要的头文件跟库文件都已编译好放在和设置在当前程序目录下,就可不用安装opencv 也能直接编译。
OpenCV中的霍夫变换可以用来检测直线和。下面分别介绍一下如何使用霍夫变换检测直线和。 1. 检测直线 首先,需要将图像转换为灰度图像,并进行边缘检测。然后,使用cv2.HoughLines函数进行霍夫变换检测直线,该函数的参数包括输入图像、霍夫变换类型、直线的距离和角度分辨率、阈值等。具体代码如下: ``` import cv2 import numpy as np # 读取图像并转换为灰度图像 img = cv2.imread('test.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 边缘检测 edges = cv2.Canny(gray, 50, 150, apertureSize=3) # 霍夫变换检测直线 lines = cv2.HoughLines(edges, 1, np.pi/180, 200) # 绘制直线 for line in lines: rho, theta = line[0] a = np.cos(theta) b = np.sin(theta) x0 = a*rho y0 = b*rho x1 = int(x0 + 1000*(-b)) y1 = int(y0 + 1000*a) x2 = int(x0 - 1000*(-b)) y2 = int(y0 - 1000*a) cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2) # 显示图像 cv2.imshow('image', img) cv2.waitKey(0) cv2.destroyAllWindows() ``` 2. 检测 同样地,需要将图像转换为灰度图像,并进行边缘检测。然后,使用cv2.HoughCircles函数进行霍夫变换检测,该函数的参数包括输入图像、霍夫变换类型、心和半径的最小值和最大值等。具体代码如下: ``` import cv2 import numpy as np # 读取图像并转换为灰度图像 img = cv2.imread('test.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 边缘检测 edges = cv2.Canny(gray, 50, 150, apertureSize=3) # 霍夫变换检测 circles = cv2.HoughCircles(edges, cv2.HOUGH_GRADIENT, 1, 20, param1=50, param2=30, minRadius=0, maxRadius=0) # 绘制 if circles is not None: circles = np.round(circles[0, :]).astype("int") for (x, y, r) in circles: cv2.circle(img, (x, y), r, (0, 255, 0), 2) # 显示图像 cv2.imshow('image', img) cv2.waitKey(0) cv2.destroyAllWindows() ``` 以上就是使用霍夫变换检测直线和的方法,希望能对你有所帮助。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值