莫张周刘王 发表于 2024-9-27 08:41:39

OpenCV第九章——图形检测

1.图像的表面       

   表面是指图形或物体的外边缘线条,简朴的多少图形是由平滑的线构成的轻易识别,但不规则图形的表面由许多个点构成,识别起来比力困难。Opencv提供了findContours()方法来判断图像的边缘,之后将边缘的点封装成数组返回,语法结构如下:
contours, hierarchy = cv2.findContours(image, mode, method)
参数说明:
image:被检测的图像,必须是8位单通道二值图像,若原始图像是彩色的,必须转化为灰度图像,并颠末二值化阈值处理
mode:表面的检索模式(下表)
https://i-blog.csdnimg.cn/direct/ad14b1ff98534fa5bf38ec5cb5d890ec.png
method:检测表面时使用的方法(下表)

https://i-blog.csdnimg.cn/direct/5d03cdb971aa4f6aa2698c6464a5442c.png
返回值说明:
contours:检测出的所有表面,list范例每一个元素都是某个表面的像素坐标数组
hierarchy:表面之间的条理关系
    OpenCV还提供了drawContours()方法用来绘制表面,语法结构如下 :
参数说明:


[*]image:要绘制表面的图像。这个图像应该是单通道(灰度图)或三通道(彩色图)的。
[*]contours:表面点集,通常是由cv2.findContours()方法返回的第二个参数(在某些版本的OpenCV中,返回值可能有所不同,但contours始终是表面点集的列表)。
[*]contourIdx:指定要绘制的表面索引。假如是-1,则绘制所有表面。
[*]color:表面的颜色。对于灰度图,它是一个标量值;对于彩色图,它是一个BGR元组(即颜色顺序是蓝、绿、红)。
[*]thickness:表面线的粗细。假如为负数(如cv2.FILLED),则表面内部将被添补。
[*]lineType:线条的范例,例如cv2.LINE_8、cv2.LINE_AA等。假如未指定,默以为cv2.LINE_8。
[*]hierarchy:表面的条理结构,由cv2.findContours()返回(在某些版本的OpenCV中可能返回)。假如不必要,可以设置为None。
[*]maxLevel:绘制表面的最大层级数,仅当hierarchy非空时才有用。假如为0,则只绘制指定的表面;假如为1,则绘制该表面及其直接子表面;依此类推。
[*]offset:表面点集的偏移量。这是一个可选参数,表示在绘制表面时,表面点会合的所有点都要加上这个偏移量。
1.1绘制多少图像的表面

操作用图:
https://i-blog.csdnimg.cn/direct/7303eb67c07f45cf9601d0faf79b28a1.jpeg
操作代码示例:
import cv2
img = cv2.imread(r"C:\Users\cgs\Desktop\pictures\5(9).jpg")# 读取原图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 彩色图像转为变成单通道灰度图像
t, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)# 灰度图像转为二值图像
# 检测图像中出现的所有轮廓,记录轮廓的每一个点
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
# 绘制所有轮廓,宽度为5,颜色为红色
cv2.drawContours(img, contours, -1, (0, 0, 255), 5)
cv2.imshow("img", img)# 显示绘制结果
cv2.waitKey()
cv2.destroyAllWindows() 操作结果图像:
https://i-blog.csdnimg.cn/direct/89ccdd542ab74cd3b9c84d2691dd9960.png
1.2绘制不规则的表面

操作用图像:
https://i-blog.csdnimg.cn/direct/6c14715b4eb5494fa567bc82df8fb656.jpeg
操作代码示例:
import cv2
img = cv2.imread(r"C:\Users\cgs\Desktop\pictures\5(10).jpg")# 读取原图
cv2.imshow("img", img)# 显示原图
img = cv2.medianBlur(img, 5)# 使用中值滤波去除噪点
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 原图从彩图变成单通道灰度图像
t, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)# 灰度图像转化为二值图像
cv2.imshow("binary", binary)# 显示二值化图像
# 获取二值化图像中的轮廓极轮廓层次数据
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
cv2.drawContours(img, contours, -1, (0, 0, 255), 2)# 在原图中绘制轮廓
cv2.imshow("contours", img)# 显示绘有轮廓的图像
cv2.waitKey()
cv2.destroyAllWindows()
结果图像:
 https://i-blog.csdnimg.cn/direct/59ff28ccfeb341539463ed1affd10d87.png
2.表面拟合

   拟合是指将平面上的一系列点用一条光滑的曲线连接起来,表面的拟合就是值将凹凸不平的表面用平整的多少图形体现出来
2.1矩形包围框

   retval = cv2.boundingRect(array)
参数说明:
array:表面数组
返回值说明:
retval: 返回一个包罗四个整数的元组 (x, y, w, h),具体含义如下:
x: 矩形的左上角的 x 坐标。
y: 矩形的左上角的 y 坐标。
w: 矩形的宽度。
h: 矩形的高度。
操作用图像:
https://i-blog.csdnimg.cn/direct/889d47e767894608b1b4ac5c26138b15.png
操作代码示例:
import cv2
img = cv2.imread(r"C:\Users\cgs\Desktop\pictures\6(1).png")# 读取原图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 从彩色图像变成单通道灰度图像
# 将灰度图像进行二值化阈值处理
t, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
# 获取二值化图像中的轮廓极轮廓层次数据
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
x, y, w, h = cv2.boundingRect(contours)# 获取第一个轮廓的最小矩形边框,记录坐标和宽高
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)# 绘制红色矩形
cv2.imshow("img", img)# 显示绘制结果
cv2.waitKey()
cv2.destroyAllWindows()

操作结果图像:
 https://i-blog.csdnimg.cn/direct/5096aea6a2cf4ac0b229cbc15330c48b.png
2.2圆形包围框

   center, radius = cv2.minEnclosingCircle(points)
参数说明:
center:元组范例,包罗两个浮点值(圆心横坐标和纵坐标)
radius;浮点范例,最小圆形包围框半径
操作代码示例:
import cv2
img = cv2.imread(r"C:\Users\cgs\Desktop\pictures\6(1).png")# 读取原图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 从彩色图像变成单通道灰度图像
# 将灰度图像进行二值化阈值处理
t, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
# 获取二值化图像中的轮廓极轮廓层次数据
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
center, radius = cv2.minEnclosingCircle(contours)# 获取最小圆形边框的圆心点和半径
x = int(round(center))# 圆心点横坐标转为近似整数
y = int(round(center))# 圆心点纵坐标转为近似整数
cv2.circle(img, (x, y), int(radius), (0, 0, 255), 2)# 绘制圆形
cv2.imshow("img", img)# 显示绘制结果
cv2.waitKey()
cv2.destroyAllWindows()
操作结果图像:
 https://i-blog.csdnimg.cn/direct/bee752e1ca6a4555912b1a926639e50f.png
3.凸包

   在OpenCV中,凸包(Convex Hull)是一个计算多少中的概念,用于形貌一个点集的最外层凸多边形。具体来说,凸包是指完全包罗原有表面,并且仅由表面上的点所构成的多边形,其特点是每一处都是凸的,即在凸包内连接恣意两点的直线都在凸包的内部,并且恣意连续3个点的内角小于180度。
    语法结构如下:
hull = cv2.convexHull(points, clockwise=None, returnPoints=True)
 
参数说明



[*]points:这是输入的点集,通常是一个NumPy数组,形状为(N, 1, 2)或(N, 2),其中N是点的数目,每个点由两个元素(通常是x和y坐标)表示。
[*]clockwise(可选):该参数指定凸包的输出方向。假如为True,则凸包的方向是顺时针的;假如为False,则为逆时针。假如未指定(即None),则凸包的方向由凸包算法的内部实现决定。
[*]returnPoints(可选):假如为True,则返回凸包上的点。假如为False,则返回凸包索引(即原始点会合的索引)。在大多数情况下,你会希望这个参数为True。
返回值



[*]hull:假如returnPoints=True,则hull是一个NumPy数组,包罗凸包上的点。这些点按凸包表面的顺序排列。
[*]假如returnPoints=False,则hull是一个包罗索引的数组,这些索引指向原始点会合的点,按凸包表面的顺序排列。
操作代码示例:
import cv2

img = cv2.imread(r"C:\Users\cgs\Desktop\pictures\6(1).png")# 读取原始图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 转为灰度图像
ret, binary = cv2.threshold(gray, 127, 225, cv2.THRESH_BINARY)# 二值化阈值处理
# 检测图像中出现的所有轮廓
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
hull = cv2.convexHull(contours)# 获取轮廓的凸包
cv2.polylines(img, , True, (0, 0, 255), 2)# 绘制凸包
cv2.imshow("img", img)# 显示图像
cv2.waitKey()
cv2.destroyAllWindows()
操作结果图像:
 https://i-blog.csdnimg.cn/direct/13364274fb3544babf5e563a3efe962c.png
4.Canny边缘检测

   Canny边缘检测算法是一种非常流行的边缘检测算法,由John F. Canny在1986年提出。该算法旨在在噪声抑制和边缘检测之间取得最佳平衡,通常通过以下步调实现:

[*] 噪声去除:起首,使用高斯滤波器平滑图像以去除噪声。这一步很重要,由于边缘检测对噪声很敏感。
[*] 计算梯度强度和方向:然后,计算图像中每个像素点的梯度强度和方向。这通常使用Sobel算子或其他梯度算子来完成。
[*] 非极大值抑制:在得到梯度强度和方向后,算法会对每个像素位置进行非极大值抑制。这一步的目标是生存局部梯度最大的点,作为边缘点。
[*] 双阈值处理和边缘连接:最后,算法使用两个阈值(高阈值和低阈值)来检测和连接边缘。起首,通过高阈值得到一个边缘图像,这个图像可能包罗一些不连续的边缘片断。然后,通过查抄由低阈值得到的边缘图像中哪些边缘片断可以连接到高阈值边缘图像中的边缘片断,来连接和规复这些边缘。
    Canny()方法语法结构:
 edges = cv2.Canny(image, threshold1, threshold2,apertureSize, L2gradient)
image:要进行边缘检测的输入图像,应为灰度图。
threshold1:第一个阈值,用于边缘连接时的低阈值。
threshold2:第二个阈值,用于检测边缘时的高阈值。
apertureSize:可选参数,Sobel算子孔径大小
L2gradient:可选参数,计算图像梯度的标识
返回值说明:
edges:输出的边缘图像,与输入图像具有相同的尺寸和范例
操作用图像:
https://i-blog.csdnimg.cn/direct/15b3d27592a94c718c2f255d8e88c19a.jpeg
操作代码示例:
import cv2
img = cv2.imread(r"C:\Users\cgs\Desktop\pictures\5(5).jpg")# 读取原图
r1 = cv2.Canny(img, 10, 50);# 使用不同的阈值进行边缘检测
r2 = cv2.Canny(img, 100, 200);
r3 = cv2.Canny(img, 400, 600);

cv2.imshow("img", img)# 显示原图
cv2.imshow("r1", r1)# 显示边缘检测结果
cv2.imshow("r2", r2)
cv2.imshow("r3", r3)
cv2.waitKey()
cv2.destroyAllWindows()
操作结果图像:
https://i-blog.csdnimg.cn/direct/148918d9cb624f53818bdf268d8b0a00.png
5.霍夫变更

   霍夫变更(Hough Transform)是一种图像处理技术,用于检测图像中的多少形状,尤其是直线和圆等常见形状。它特殊适用于处理有噪声的图像数据,由于它可以或许在特性空间中找到形状,即使在图像中这些形状可能是断裂的或者被遮挡的。
5.1 直线检测

   OpenCV中的HoughLinesP()方法

HoughLinesP() 是 OpenCV 中用于直线检测的函数之一,与 HoughLines() 相比,HoughLinesP() 可以或许直接返回直线的两个端点,这对于后续处理(如绘制直线)更为方便。
    lines = cv2.HoughLinesP(image, rho, theta, threshold, minLineLength=0, maxLineGap=0)
参数说明:
image: 输入图像,应该是边缘检测后的二值图像(通常是Canny边缘检测的结果)。
rho:检测直线使用的半径步长,值为1时,表示检测所有可能的半径步长
theta: 以弧度为单元的θ的精度。
threshold: 累加器平面的阈值参数。只有那些获得足够交点的曲线才被返回。
minLineLength: 最小线段长度。比这个长度短的线段将被拒绝。
maxLineGap: 线段上最大隔断,用于将同一行上的点连接成线段。假如隔断大于此值,则视为两条线段。
操作用图像:
https://i-blog.csdnimg.cn/direct/0a51e1c708e84cd78af672bda2b56bc9.jpeg

操作代码示例:
import cv2
import numpy as np

img = cv2.imread(r"C:\Users\cgs\Desktop\pictures\pen.jpg")# 读取原图
o = img.copy()# 复制原图
o = cv2.medianBlur(o, 5)# 使用中值滤波进行降噪
gray = cv2.cvtColor(o, cv2.COLOR_BGR2GRAY)# 从彩色图像变成单通道灰度图像
binary = cv2.Canny(o, 50, 150)# 绘制边缘图像
# 检测直线,精度为1,全角度,阈值为15,线段最短100,最小间隔为18
lines = cv2.HoughLinesP(binary, 1, np.pi / 180, 15, minLineLength=100, maxLineGap=18)
for line in lines:# 遍历所有直线
    x1, y1, x2, y2 = line# 读取直线两个端点的坐标
    cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2)# 在原始图像上绘制直线
cv2.imshow("canny", binary)# 显示二值化边缘图案
cv2.imshow("img", img)# 显示绘制结果
cv2.waitKey()
cv2.destroyAllWindows()

操作结果图像: 
https://i-blog.csdnimg.cn/direct/ca50347b534a4d1f85096b401f4c5b4b.png
5.2圆环检测

   OpenCV中的HoughCircles()方法

在OpenCV中,HoughCircles()函数用于实现基于霍夫变更的圆环检测。它返回图像中检测到的圆的参数(圆心和半径)
     cv2.HoughCircles(image, method, dp, minDist, param1=100, param2=100, minRadius=0, maxRadius=0)
参数说明:
image:原始图像
method:检测圆的方法。目前OpenCV中唯一实现的方法是cv2.HOUGH_GRADIENT,它基于边缘的梯度信息。
dp:累加器分辨率与图像分辨率的反比。例如,假如dp=1,则累加器和输入图像具有相同的分辨率。dp=2,累加器分辨率是图像分辨率的一半。
minDist:检测到的圆心之间的最小距离。假如参数设置得太小,则可能会错误地检测到多个相邻的圆。
param1:Canny边缘检测器的高阈值(第一阶段)。记着,低阈值是高阈值的一半。
param2:累加器阈值,即识别为圆所需的投票数。参数值越高,检测到的圆越完美。
minRadius:圆半径的最小值。
maxRadius:圆半径的最大值。
返回值说明:
circles:函数返回一个包罗圆参数(x, y, radius)的NumPy数组,每个圆占用数组的一行。假如未找到圆,则返回None。
操作用图像:
https://i-blog.csdnimg.cn/direct/cd15447c30ca48aeb89664ac2bb8bf66.jpeg
操作代码示例:
import cv2
import numpy as np

img = cv2.imread(r"C:\Users\cgs\Desktop\pictures\6(2).jpg")# 读取原图
o = img.copy()# 复制原图
o = cv2.medianBlur(o, 5)# 使用中值滤波进行降噪
gray = cv2.cvtColor(o, cv2.COLOR_BGR2GRAY)# 从彩色图像变成单通道灰度图像
# 检测圆环,圆心最小间距为70,Canny最大阈值为100,投票数超过25。最小半径为10,最大半径为50
circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 70, param1=100, param2=25, minRadius=10, maxRadius=50)
circles = np.uint(np.around(circles))# 将数组元素四舍五入成整数
for c in circles:# 遍历圆环结果
    x, y, r = c# 圆心横坐标、纵坐标和圆半径
    cv2.circle(img, (x, y), r, (0, 0, 255), 3)# 绘制圆环
    cv2.circle(img, (x, y), 2, (0, 0, 255), 3)# 绘制圆心
cv2.imshow("img", img)# 显示绘制结果
cv2.waitKey()
cv2.destroyAllWindows()
操作结果图像:
 https://i-blog.csdnimg.cn/direct/3e4832bd7d0044d3b517ef6926416093.png
有关表面检测的内容就到这里了,感谢各人的观看!!! 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: OpenCV第九章——图形检测