Python+Opencv实现多种形状的检测
目录
- 一、Hough变换是什么?
- 二、Hough变换原理简介
- 三、Hough变换实现步骤
- 四、Hough变换直线检测代码实现及效果展示
- 五、Hough变换圆形检测代码实现及效果展示
- 六、基于Hough的椭圆检测代码实现及效果展示
- 七、轮廓检测不同形状代码实现及效果展示
- 八、获取图像中的黑色形状块
- 九、移除图中的圆和椭圆
- 十、思维扩展
- 参考资料
- 注意事项
一、Hough变换是什么?
Hough变换是由 P.V.C.Hough提出的一种算法,这种算法可以快速、准确的检测出图片中的直线、圆和椭圆等多种形状。在计算机视觉领域中得到了广泛的使用。
二、Hough变换原理简介
Hough变换是一种特征提取算法,它已经被广泛的应用在机器视觉、图像分析和影像处理等多个方面。Hough变换的主要用途包括寻找图像中直线、圆或椭圆等在图像中的具体位置,其主要的原理是将图像转换到Hough变换空间中,将直角坐标系中的点转换到极坐标系中,通过数学关系的推导,我们可以得到直角坐标系中的直线对应到极坐标系中就是多条曲线的交点,即图像空间中的直线检测问题转化到Hough空间就成了检测曲线的汇集点点的问题。
Hough变换的基本思想是基于点和线的对偶关系,图像空间XY中,所有通过点(x,y)的点所表示的方程为:y=px+q\mathrm{y}=p x+qy=px+q;其中P表示的是直线的斜率,q表示直线的截距,也可以表示为q=−px+yq=-p x+yq=−px+y;如下图所示,图像空间中过(xi,yj)\left(x_{i}, y_{j}\right)(xi,yj)点的直线方程可以表示成yi=pxi+qy_{i}=p x_{i}+qyi=pxi+q;也可以在参数空间中表示为q=−pxi+yiq=-p x_{i}+y_{i}q=−pxi+yi。
通过上图我们可以得出图像空间中共线的点和参数空间中的相交的线具有一一对应的关系;参数空间中相交于同一点的所有直线和图像空间中贡献的点相互对应,这就是所谓的点和线之间的对偶关系。Hough变换就是按照这种关系来将图像空间中的检测问题转变成参数空间中寻找交叉点,然后在参数空间中执行简单的累计统计来完成直线的检测任务。当直线接近于竖直方向时,此时我们用极坐标方程来表示该直线。具体的方程可以表示为λ=xcosθ+ysinθ\lambda=x \cos \theta+y \sin \thetaλ=xcosθ+ysinθ;根据上式,我们可以得出对于极坐标系中的任意一组点(λ,θ)(\lambda, \theta)(λ,θ)都对应这一条直线,即这里将点和线的对偶关系转变成了点和正弦曲线的对偶关系。如下图所示,图a表示的是图像空间中的5个坐标点,它们和图b中的5条曲线相互对应,θ∈[−90,+90],λ∈[−2N2,+2N2]\theta \in[-90,+90], \quad \lambda \in\left[-\frac{\sqrt{2} N}{2},+\frac{\sqrt{2} N}{2}\right]θ∈[−90,+90],λ∈[−22N,+22N],其中N表示图像的宽度。即图像空间中的的点和参数空间中的曲线相互对应,图b中的曲线1、3、5这3条曲线都经过K点,对应到图像空间中表示1、3、5处于同一条直线上面;图a中的2、3、4这3个点处于同一条直线上,对应于参数空间中表示它们所对应的曲线2、3、4都通过同一点L。
三、Hough变换实现步骤
- 步骤1-首先建立一个二维数组,其对应的参数空间为,这个数组其实就相当于一个累加器;
- 步骤2-然后使用顺序搜索的方式在图像中的所有目标像素中进行快速的搜索,针对图像中的每一个像素而言,在参数空间中根据式λ=xcosθ+ysinθ\lambda=x \cos \theta+y \sin \thetaλ=xcosθ+ysinθ计算出一个对应的位置,在累加器对应的位置上执行一次加1操作;
- 步骤3-然后求出累加器中的最大值,也就是参数空间中的最大值,其对应的位置为(λ′,θ′)\left(\lambda^{\prime}, \theta^{\prime}\right)(λ′,θ′);
- 步骤4-最后将获得的参数空间位置(λ′,θ′)\left(\lambda^{\prime}, \theta^{\prime}\right)(λ′,θ′)输入到式λ=xcosθ+ysinθ\lambda=x \cos \theta+y \sin \thetaλ=xcosθ+ysinθ中,从而找到该空间所对应的图像空间中的直线参数,即我们需要检测的结果。
四、Hough变换直线检测代码实现及效果展示
# coding=utf-8# 导入python库
import cv2
import numpy as np
import matplotlib.pyplot as plt# 读取图片
img = cv2.imread('test3.jpg')
# 彩色图片灰度化
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# 执行边缘检测
edges = cv2.Canny(gray,100,200)
# 显示原始结果cv2.imwrite('edges.png',edges)
cv2.imshow('edge', edges)
# plt.subplot(121)
# plt.imshow(edges)# 执行Hough直线检测
lines = cv2.HoughLines(edges,1,np.pi/180,160)
lines1 = lines[:,0,:]
for rho,theta in lines1:a = np.cos(theta)b = np.sin(theta)x0 = a*rhoy0 = b*rhox1 = 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),(255,0,0),1)cv2.imwrite('line.png',img)
cv2.imshow('line', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
# plt.subplot(122)
# plt.imshow(img)
上图展示了Hough变换直线检测的结果。第1列表示的是原始的输入图片;第2列表示的是边缘检测的结果;第3列表示Hough直线检测结果。我们可以发现Hough变换准确的检测到图片中的所有直线。需要主要的是用户需要根据自己的需要对边缘检测的参数进行调节。
五、Hough变换圆形检测代码实现及效果展示
# coding=utf-8
# 导入python包
import numpy as np
import argparse
import cv2# 构建并解析参数
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required = True, help = "Path to the image")
args = vars(ap.parse_args())# 读取彩色图片
image = cv2.imread(args["image"])
output = image.copy()
# 将其转换为灰度图片
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# 应用hough变换进行圆检测
circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1.2, 100)# 确保至少发现一个圆
if circles is not None:# 进行取整操作circles = np.round(circles[0, :]).astype("int")# 循环遍历所有的坐标和半径for (x, y, r) in circles:# 绘制结果cv2.circle(output, (x, y), r, (0, 255, 0), 4)cv2.rectangle(output, (x - 5, y - 5), (x + 5, y + 5), (0, 128, 255), -1)# 显示结果cv2.imshow("output", np.hstack([image, output]))cv2.waitKey(0)
上图展示了Hough变换圆形检测的结果。每一行表示一个测试图片,第1列表示的是原始的输入图片,第2列表示的是Hough检测的结果。通过上图我们可以获得一些信息,即Hough变换不仅能够处理简单的情况,也能很好的处理复杂的情况。需要注意的是用户需要根据自己的输入图片去调节cv2.HoughCircles函数中的一些关键参数。
六、基于Hough的椭圆检测代码实现及效果展示
# coding=utf-8import matplotlib.pyplot as plt
from skimage import data,draw,color,transform,feature#加载图片,转换成灰度图并检测边缘
image_rgb = data.coffee()[0:220, 160:420] #裁剪原图像,不然速度非常慢
image_gray = color.rgb2gray(image_rgb)
edges = feature.canny(image_gray, sigma=2.0, low_threshold=0.55, high_threshold=0.8)#执行椭圆变换
result =transform.hough_ellipse(edges, accuracy=20, threshold=250,min_size=100, max_size=120)
result.sort(order='accumulator') #根据累加器排序#估计椭圆参数
best = list(result[-1]) #排完序后取最后一个
yc, xc, a, b = [int(round(x)) for x in best[1:5]]
orientation = best[5]#在原图上画出椭圆
cy, cx =draw.ellipse_perimeter(yc, xc, a, b, orientation)
image_rgb[cy, cx] = (0, 0, 255) #在原图中用蓝色表示检测出的椭圆# #分别用白色表示canny边缘,用红色表示检测出的椭圆,进行对比
# edges = color.gray2rgb(edges)
# edges[cy, cx] = (250, 0, 0) fig2, (ax1, ax2) = plt.subplots(ncols=2, nrows=1, figsize=(8, 4))ax1.set_title('Original picture')
ax1.imshow(image_rgb)ax2.set_title('Detect result')
ax2.imshow(edges)plt.show()
上图展示了Hough变换椭圆检测的结果。第1列表示的是原始的输入图片,图中的蓝线表示检测的结果;第2列表示检测的结果,并将其绘制在一张存在的图片中。图中可以看出Hough变换可以很好的检测出图片中的椭圆。
七、轮廓检测不同形状代码实现及效果展示
# coding=utf-8
# 导入python包
import cv2# 读取彩色图片
img = cv2.imread('rect1.png')
# 转换为灰度图片
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 进行二值化处理
ret,binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)# 寻找轮廓
_,contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)# 绘制不同的轮廓
draw_img0 = cv2.drawContours(img.copy(),contours,0,(0,255,255),3)
draw_img1 = cv2.drawContours(img.copy(),contours,1,(255,0,255),3)
draw_img2 = cv2.drawContours(img.copy(),contours,2,(255,255,0),3)
draw_img3 = cv2.drawContours(img.copy(), contours, -1, (0, 0, 255), 3)# 打印结果
print ("contours:类型:",type(contours))
print ("第0 个contours:",type(contours[0]))
print ("contours 数量:",len(contours))print ("contours[0]点的个数:",len(contours[0]))
print ("contours[1]点的个数:",len(contours[1]))# 显示并保存结果
cv2.imshow("img", img)
cv2.imshow("draw_img0", draw_img0)
cv2.imshow("draw_img1", draw_img1)
cv2.imshow("draw_img2", draw_img2)
cv2.imwrite("rect_result.png", draw_img3)
cv2.imshow("draw_img3", draw_img3)cv2.waitKey(0)
cv2.destroyAllWindows()
上图展示了利用轮廓检测不同形状的结果。每一行展示了一个测试图片,第1列展示的是输入图片,第2类展示的是输出结果。通过上图我们可以看到轮廓检测算法可以准确的检测到图中的所有轮廓并准确的将他们绘制出来。这在现实场景中具有很广泛的应用价值。
八、获取图像中的黑色形状块
# coding=utf-8
# 导入python包
import numpy as np
import argparse
import imutils
import cv2# 构建并解析参数
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", help = "path to the image file")
args = vars(ap.parse_args())# 读取图片
image = cv2.imread(args["image"])# 寻找到图片中的黑色形状块
lower = np.array([0, 0, 0])
upper = np.array([15, 15, 15])
shapeMask = cv2.inRange(image, lower, upper)# 在mask中寻找轮廓
cnts = cv2.findContours(shapeMask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
print("I found {} black shapes".format(len(cnts)))
cv2.imwrite("Mask.png", shapeMask)
cv2.imshow("Mask", shapeMask)# 循环遍历所有的轮廓
for c in cnts:# draw the contour and show itcv2.drawContours(image, [c], -1, (0, 255, 0), 2)
cv2.imwrite("shape1.png", image)
cv2.imshow("Image", image)
cv2.waitKey(0)
上图展示了使用python+opencv自动检测到图像中的黑色形状块,第1列表示的是原始的输入图片,和代码中的image对应;第2列表示的是获取到的掩模,对应于代码中的shapeMask;第3列表示的是检测的结果,对应于代码中的image。通过上图我们可以发现该算法能够准确的检测出这些不同的形状块。
九、移除图中的圆和椭圆
# coding=utf-8
# 导入python包
import numpy as np
import imutils
import cv2def is_contour_bad(c):# 近似轮廓peri = cv2.arcLength(c, True)approx = cv2.approxPolyDP(c, 0.02 * peri, True)# 判断当前的轮廓是不是矩形return not len(approx) == 4# 首先读取图片;然后进行颜色转换;最后进行边缘检测
image = cv2.imread("remove.png")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
edged = cv2.Canny(gray, 50, 100)
cv2.imshow("Original", image)# 寻找图中的轮廓并设置mask
cnts = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
mask = np.ones(image.shape[:2], dtype="uint8") * 255# 循环遍历所有的轮廓
for c in cnts:# 检测该轮廓的类型,在新的mask中绘制结果if is_contour_bad(c):cv2.drawContours(mask, [c], -1, 0, -1)# 移除不满足条件的轮廓并显示结果
image = cv2.bitwise_and(image, image, mask=mask)
cv2.imwrite("Mask.png", mask)
cv2.imshow("Mask", mask)
cv2.imwrite("result.png", image)
cv2.imshow("After", image)
cv2.waitKey(0)
十、思维扩展
在现实场景中,我们经常会遇到检测图片中具有不同形状的目标的任务。本文主要关注的是直线、圆、椭圆、三角形等,对于那些不规则的形状而言,其实Opencv中已经内嵌了其它的函数,聪明的你一定可以找到这个函数完成一些更加复杂的形状检测任务。
参考资料
[1] 参考链接
注意事项
[1] 该博客是本人原创博客,如果您对该博客感兴趣,想要转载该博客,请与我联系(qq邮箱:1575262785@qq.com),我会在第一时间回复大家,谢谢大家的关注.
[2] 由于个人能力有限,该博客可能存在很多的问题,希望大家能够提出改进意见。
[3] 如果您在阅读本博客时遇到不理解的地方,希望您可以联系我,我会及时的回复您,和您交流想法和意见,谢谢。
[4] 本文测试的图片可以通过该链接进行下载。网盘链接- 提取码:oluh 。
[5] 本人业余时间承接各种本科毕设设计和各种小项目,包括图像处理(数据挖掘、机器学习、深度学习等)、matlab仿真、python算法及仿真等,有需要的请加QQ:1575262785详聊!!!
Python+Opencv实现多种形状的检测相关推荐
- Python OpenCV Tesseract实现车牌的检测与识别
python+opencv+TESSERT-OCR实现车牌的检测与识别_啥都不会的小王的博客-CSDN博客python+opencv+TESSERT-OCR实现车牌的检测与识别开学花了十天时间0基础搞 ...
- Python+Opencv颜色和形状检测
目录 一.场景需求解读 二.算法原理简介 三.算法实现步骤 四.算法代码实现 五.算法效果展示与分析 参考资料 注意事项 一.场景需求解读 现实场景中,我们有时需要自动的检测出图片中目标的颜色和其 ...
- python颜色形状识别_Python学习(10)Python+Opencv颜色和形状检测
目录 一.场景需求解读 现实场景中,我们有时需要自动的检测出图片中目标的颜色和其对应的形状,然后根据这些信息快速的找到我们需要的目标,这在真实场景中具有广泛的应用.下图展示了一张实例,我们需要知道图片 ...
- 使用Python+OpenCV+yolov5实现行人目标检测
点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自 | 深度学习与计算机视觉 介绍 目标检测支持许多视觉任务 ...
- 使用Python+OpenCV+detectorn2实现社交距离检测
点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 介绍 美国和欧洲的许多城市现在都在谨慎地重新开放.人们被要求在外出 ...
- python人脸口罩识别_基于Python+OpenCV的人脸口罩识别检测
以下编程在Jupyter notbook平台上进行 一.OpenCV下载安装 二.人脸口罩数据集下载处理 (一)人脸口罩数据集下载 下载人脸口罩数据集的目的是利用OpenCV进行模型训练,这里采用口罩 ...
- Python+Opencv实现实时的条形码检测
目录 一.场景需求简介 二.算法实现步骤 三.图片中条形码检测代码实现 四.图片中条形码检测效果展示与分析 五.视频中条形码检测代码实现 六.视频中条形码检测效果展示与分析 七.思维扩展 参考资料 注 ...
- Python+Opencv根据颜色进行目标检测
目录 一.什么是颜色目标检测? 二.如何实现基于颜色的目标检测? 三.算法代码实现 四.算法运行流程 五.效果展示与分析 六.思维扩展 参考资料 注意事项 一.什么是颜色目标检测? 所谓的颜色目标 ...
- python opencv根据颜色进行目标检测
颜色目标检测就是根据物体的颜色快速进行目标定位.使用cv2.inRange函数设定合适的阈值,即可以选出合适的目标. 建立项目colordetect.py,代码如下: #! /usr/bin/ ...
最新文章
- 删除空值_空白单元格行,如何快速批量删除?简单方法,效率飞升
- ORACLE SQL: 经典查询练手第二篇
- 计算机背景象怎样改变,我的页面背景总是黑色,以前改变过现在好象改变不了?我该怎么改变呢? 爱问知识人...
- 得出来的视差图左边有黑色补上原图_「PS教程」Photoshop使用通道快速抠图的详细教程...
- mongodb视频教程云盘,深度讲解Java多线程开发—电子表项目实现
- 【PAT乙级】1069 微博转发抽奖 (20 分)
- LeetCode 321. 拼接最大数(单调栈)*
- python中字符集
- Android 系统(66)---Android硬件加速相关问题总结
- java异常体系简介
- AcWing 741. 斐波那契数列
- 传奇微端需要下载客户端吗?传奇微端架设教程,微端配置教程
- 大麦 Android 选座场景性能优化全解析
- 干货!手把手教你搭建高可用架构
- 松翰单片机 c语言例程 宏定义出错,松翰单片机 SN8F5702程序例程
- 好好说话之hijack GOT
- 美食app的UI设计
- 数据分析研究思维导图
- element 配置全局样式 例如:为项目中所有el-dialog弹窗添加分割线
- pinyin4j:拼音与汉字的转换实例