【Opencv-图形检测】

图像的轮廓

  • 简单的图像容易识别,复杂的图像比较难。Opencv提供findContours()方法通过计算图像梯度判断图像的边缘,然后将边缘的点封装成数组反回。语法格式如下。
contours,hierarchy = cv2.findCountours(image,mode,methode)
'''
参数说明:
- image:被检测的图像,必须是8位单通道二值图像。如果是彩色图像必须转换成灰度图像,并经过二值化处理
- mode:轮廓的检测点,具体详见表9.1
- methode:检测轮廓时使用的方法,具体值详见9.2
- contours:检测出的所有轮廓,list类型,每一个元素都是下像素元素的坐标数组
- heirarchy:轮廓之间的层次关系
'''
  • 通过findContours()方法找到轮廓后,为了方便观测,提供drawContours()方法专门用来绘制这些轮廓。
image = cv2.drawContours(image,contours,contourIdx,color,thickness,lineTypee,
hierarchy,mexLevel,offse)
'''
- image:原始图像
- contours:findContours()绘制得到的轮廓列表
- contourIdx:绘制轮廓的索引,如果为-1则绘制所有轮廓
- color:绘制颜色,使用BGR格式
- 以下是可选参数:
- thickness:画笔的粗细长度如果是-1则是实心绘制
- lineTypee:绘制轮廓的线性
- hierarchy:findContours()方法得到的层次关系
- maxLevel:偏移量可以改变绘制结果的位置
- image:返回结果图像
'''

【Opencv-图形检测】_第1张图片
【Opencv-图形检测】_第2张图片

import cv2
img = cv2.imread("shape1.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_NONE)
# 绘制所有轮廓,宽度为5,颜色为红色
cv2.drawContours(img, contours, -1, (0, 0, 255), 5)
cv2.imshow("img", img)  # 显示绘制结果
cv2.waitKey()  # 按下任何键盘按键后
cv2.destroyAllWindows()  # 释放所有窗体
  • 下面这个代码有个小bug必须把检测外轮廓的代码放到前面才能把两个效果都呈现出来,不然只会呈现image1的效果
import cv2
img = cv2.imread("shape1.png")  # 读取原图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 彩色图像转为变成单通道灰度图像
t, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)  # 灰度图像转为二值图像

#使用cv2.RETR_EXTERNAL做参数绘制外轮廓
contours1, hierarchy1 = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
img2 = cv2.drawContours(img, contours1, -1, (0, 0, 255), 5)
cv2.imshow("img2", img2)  # 显示绘制结果

# 检测图像中出现的所有轮廓,记录轮廓的每一个点
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
# 绘制所有轮廓,宽度为5,颜色为红色
img1 = cv2.drawContours(img, contours, -1, (0, 0, 255), 5)
cv2.imshow("img1", img1)  # 显示绘制结果

cv2.waitKey()  # 按下任何键盘按键后
cv2.destroyAllWindows()  # 释放所有窗体
  • 可以使用以下解决方法,把同一个图像读取多次
img = cv2.imread("shape1.png")  # 读取原图
img1 = cv2.imread("shape1.png")  # 读取原图
img2 = cv2.imread("shape1.png")  # 读取原图
img3 = cv2.imread("shape1.png")  # 读取原图

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 彩色图像转为变成单通道灰度图像
t, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)  # 灰度图像转为二值图像
#使用cv2.RETR_EXTERNAL做参数绘制外轮廓
contours, hierarchy = cv2.findContours(binary, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_NONE)
img0 = cv2.drawContours(img, contours, 0, (0, 0, 255), 5)
img1 = cv2.drawContours(img1, contours, 1, (0, 0, 255), 5)
img2 = cv2.drawContours(img2, contours, 2, (0, 0, 255), 5)
img3 = cv2.drawContours(img3, contours, 3, (0, 0, 255), 5)

cv2.imshow("img0", img0)  # 显示绘制结果
cv2.imshow("img1", img1)
cv2.imshow("img2", img2)
cv2.imshow("img3", img3)

cv2.waitKey()  # 按下任何键盘按键后
cv2.destroyAllWindows()  # 释放所有窗体

轮廓拟合

  • 拟合是指将平面上一系列的点,用一条光滑的曲线连接起来。轮廓拟合说就是将凹凸不平的轮廓用平整的几何图形体现出来。
矩形包围框
矩形包围框是指图像轮廓的最小矩形边界。Opencv提供了bounddingRect()方法。
retval = cv2.boundingRect(arry)
'''
marry:轮廓数组
retval:元组类型,包含四个整数值,分别是最小矩形包围框在左上角顶点的横坐标,左上角顶点纵坐标,矩形的宽和高。也可以写成x,y,w,h=cv2.boundingRect(array)
'''
圆形包围框
矩形包围框是指图像轮廓的最小矩形边界。Opencv提供了bounddingRect()方法。
center,radius = cv2.minEnclosingCircle(points)
'''
points:轮廓数组
center:元组类型,包含两个浮点值,是最小圆形包围框圆心的横坐标和纵坐标
radius:浮点类型,最小圆形包围框半径
'''
import cv2
img = cv2.imread("shape2.png")  # 读取原图
img1 = cv2.imread("shape2.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[0])  # 获取最小圆形边框的圆心点和半径
x1 = int(round(center[0]))  # 圆心点横坐标转为近似整数
y1 = int(round(center[1]))  # 圆心点纵坐标转为近似整数
cv2.circle(img1, (x1, y1), int(radius), (0, 0, 255), 2)  # 绘制圆形

x, y, w, h = cv2.boundingRect(contours[0])  # 获取第一个轮廓的最小矩形边框,记录坐标和宽高
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)  # 绘制红色矩形
cv2.imshow("img", img)  # 显示绘制结果
cv2.imshow("img1", img1)  # 显示绘制结果
cv2.waitKey()  # 按下任何键盘按键后
cv2.destroyAllWindows()  # 释放所有窗体

凸包

  • 找出最外层的端点,将这些端点连接起来,就可以围出一个包围图像的最小包围框,这种包围框就叫凸包。
    【Opencv-图形检测】_第3张图片
#convexHull()方法
hull = cv2.convexHull(points,clockwise,returnPoints)
'''
points:轮廓数组
clockwise:可选参数,布尔类型,当该值为Ture时,凸包中的点按顺时针排列;当为Flase时按逆时针排列。
returnPoints:可选参数,布尔类型,为Ture时返回点坐标,为Flash时返回点索引。默认为Ture
hull:凸包的点阵数组。
'''
import cv2

img = cv2.imread("shape2.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[0])  # 获取轮廓的凸包
cv2.polylines(img, [hull], True, (0, 0, 255), 2)  # 绘制凸包
cv2.imshow("img", img)  # 显示图像
cv2.waitKey()  # 按下任何键盘按键后
cv2.destroyAllWindows()  # 释放所有窗体

Canny边缘检测

  • 是一个多级边缘检测方法,该算法根据像素梯度变化寻找图像边缘,最终可以绘制出十分精确的二值边缘图像。Opencv提供了Canny()方法中。
edges = cv2.Canny(image,threshold1,threshold2,apertureSize,L2gradient)
'''
image:检测原始图像
threshold1:计算过程中使用的第一个阈值,可以是最小阈值,也可以是最大阈值,通常用来设置最小阈值
threshold2:计算过程中使用的第2个阈值,通常用来设置最大阈值
apertureSize:可选参数,Sobel算子的孔径大小
L2gradient:可选参数,计算图像梯度的标识,默认值为Flash.值为Ture时会采用更精准的算法进行计算
edges:计算后得出的边缘图像,是一个二值灰度图像
在开发过程中通过调整最小阈值和最大阈值来控制边缘检测的精细程度,当两个阈值都比较小时,会检测出更多细节,当两个阈值都比较大时,会忽略较多细节
'''
import cv2
img = cv2.imread("flower.png")  # 读取原图
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()  # 释放所有窗体

霍夫变换

  • 霍夫变换是一种特征检测,通过算法识别图像的特征,从而判断出图像的特殊形状,例如直线和园。
直线检测


【Opencv-图形检测】_第4张图片

import cv2
import numpy as np

img = cv2.imread("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[0]  # 读取直线两个端点的坐标
    cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2)  # 在原始图像上绘制直线
cv2.imshow("canny", binary)  # 显示二值化边缘图案
cv2.imshow("img", img)  # 显示绘制结果
cv2.waitKey()  # 按下任何键盘按键后
cv2.destroyAllWindows()  # 释放所有窗体

圆环检测

import cv2
import numpy as np

img = cv2.imread("coin.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[0]:  # 遍历圆环结果
    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()  # 释放所有窗体

【Opencv-图形检测】_第5张图片

你可能感兴趣的:(笔记,python)