OpenCV学习+常用函数记录③:霍夫变换与轮廓提取
2020-11-01 18:52
771 查看
OpenCV 霍夫变换与轮廓提取
3. 霍夫变换
首先放上霍夫变换官方文档:[霍夫直线变换官网文档]
3.1 霍夫直线
import cv2 as cv import matplotlib.pyplot as plt import numpy as np # 1. 将图片以灰度的方式读取进来 img = cv.imread("../img/weiqi.jpg", cv.IMREAD_COLOR) gray_img = cv.cvtColor(img, cv.COLOR_BGR2GRAY) # 2. 将图片转成二值图 _, thresh_img = cv.threshold(gray_img, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_OTSU) # 3. 霍夫变换 # 线段以像素为单位的距离精度,double类型的,推荐用1.0 rho = 1 # 线段以弧度为单位的角度精度,推荐用numpy.pi/180(弧度变换的步长) theta = np.pi / 180 # 累加平面的阈值参数,int类型,超过设定阈值才被检测出线段,值越大,基本上意味着检出的线段越长,检出的线段个数越少。(一条直线至少包含十个像素点) threshold = 10 # 线段以像素为单位的最小长度 min_line_length = 25 # 同一方向上两条线段判定为一条线段的最大允许间隔(断裂),超过了设定值,则把两条线段当成一条线段,值越大,允许线段上的断裂越大,越有可能检出潜在的直线段 max_line_gap = 3 lines = cv.HoughLinesP(thresh_img, rho, theta, threshold, minLineLength=min_line_length, maxLineGap=max_line_gap) dst_img = img.copy() for line in lines: x1, y1, x2, y2 = line[0] cv.line(dst_img, (x1, y1), (x2, y2), (0, 0, 255), 2) cv.imshow("src", img) cv< 12bcb span class="token punctuation">.imshow("gray_img", gray_img) cv.imshow("thresh_img", thresh_img) cv.imshow("dst_img", dst_img) cv.waitKey(0)
3.2 霍夫圆
import cv2 as cv import numpy as np # 1. 将图片以灰度的方式读取进来 img = cv.imread("../img/weiqi.jpg", cv.IMREAD_COLOR) gray_img = cv.cvtColor(img, cv.COLOR_BGR2GRAY) # 2. 霍夫圆形检测 def hough_circle(gray_img): # 定义检测图像中圆的方法。目前唯一实现的方法是cv2.HOUGH_GRADIENT method = cv.HOUGH_GRADIENT # 累加器分辨率与图像分辨率的反比。例如,如果dp = 1,则累加器具有与输入图像相同的分辨率。如果dp = 2,则累加器的宽度和高度都是一半。 dp = 1 # 检测到的圆的圆心之间最小距离。如果minDist太小,则可能导致检测到多个相邻的圆。如果minDist太大,则可能导致很多圆检测不到。 minDist = 20 # param1 Canny算法阈值上线 # param2 cv2.HOUGH_GRADIENT方法的累加器阈值。阈值越小,检测到的圈子越多。 # minRadius : 最小的半径,如果不确定,则不指定 # maxRadius : 最大的半径,若不确定,则不指定 circles = cv.HoughCircles(gray_img, method, dp, minDist=minDist, param1=70, param2=30, minRadius=0, maxRadius=20) dst_img = img.copy() for circle in circles[0, :]: # 圆心坐标,半径 x, y, r = circle # 绘制圆心 cv.circle(dst_img, (x, y), 2, (0, 255, 0), 1) # 绘制圆形 cv.circle(dst_img, (x, y), r, (0, 0, 255), 2) cv.imshow("src", img) cv.imshow("result", dst_img) # 3. 调用函数,寻找霍夫圆 hough_circle(gray_img) cv.waitKey(0) cv.destroyAllWindows()
4. 轮廓提取
- 基于图像边缘提取或二值化的基础寻找对象轮廓
- 边缘提取的阈值会最终影响轮廓发现的结果
- 主要API有以下两个
findContours
发现轮廓 drawContours
绘制轮廓
4.1 查找轮廓
处理的图像, 轮廓列表, 继承关系 = cv.findContours(图像, 轮廓检索模式, 轮廓检索算法) # hierarchy[i][3],分别表示第i个轮廓的后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号
轮廓检索模式:
RETR_EXTERNAL只检测最外层轮廓
RETR_LIST提取所有轮廓,并放置在list中,检测的轮廓不建立等级关系
RETR_CCOMP提取所有轮廓,并将轮廓组织成双层结构(two-level hierarchy),顶层为连通域的外围边界,次层位内层边界
RETR_TREE提取所有轮廓并重新建立网状轮廓结构
轮廓检索算法:
CHAIN_APPROX_NONE获取每个轮廓的每个像素,相邻的两个点的像素位置差不超过1
CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的重点坐标,如果一个矩形轮廓只需4个点来保存轮廓信息
CHAIN_APPROX_TC89_L1Teh-Chinl链逼近算法
CHAIN_APPROX_TC89_KCOSTeh-Chinl链逼近算法
4.2 绘制轮廓
cv.drawContours(图像, 轮廓列表, 轮廓索引 如-1则绘制所有, 轮廓颜色, 轮廓的宽度)
((x,y),radius) = cv.minEnclosingCircle(contour) # 绘制外切圆
实现步骤:
- 读取图片
- 将图片转成一张灰色图片
- 对图片进行二值化处理
- 使用findContours查找轮廓
- 对轮廓进行处理
import cv2 as cv # 1. 读取图片 def read_rgb_img(img_name): rgb_img = cv.imread(img_name, cv.IMREAD_COLOR) cv.imshow("rgb img", rgb_img) return rgb_img # 2. 将图片转成一张灰色图片 def convert_rgb2gray(img): gray_img = cv.cvtColor(img, cv.COLOR_BGR2GRAY) return gray_img # 3. 对图片进行二值化处理 def convert_gray2binary(img): # binary_img = cv.adaptiveThreshold(img, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 5, 2) _, binary_img = cv.threshold(img, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_OTSU) return binary_img # 4. 使用findContours查找轮廓 def getContours(img): _, contours, hierarchy = cv.findContours(img, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE) print(contours, hierarchy) return contours # 5. 对轮廓进行处理 def draw_contours(img, contours): index = -1 # 所有的轮廓 thickness = 2 # 轮廓的宽度 color = (255, 125, 125) # 轮廓的颜色 imgg = cv.drawContours(img, contours, index, color, thickness) cv.imshow('draw contours', imgg) # 画出轮廓图 for i, c in enumerate(contours): circle = cv.minEnclosingCircle(c) ((x, y), radius) = circle cv.circle(imgg, (int(x), int(y)), int(radius), (0, 0, 255), 2) if __name__ == '__main__': img_name = "../img/shape.jpg" rgb_img = read_rgb_img(img_name) gray_img = convert_rgb2gray(rgb_img) binary_imgage = convert_gray2binary(gray_img) contours = getContours(binary_imgage) draw_contours(rgb_img, contours) cv.imshow("gray_img", gray_img) # 画出灰度图 cv.imshow("binary_img", binary_imgage) # 画出二值图 cv.imshow('draw_contours_circle', rgb_img) # 画出有外接圆的轮廓图 cv.waitKey(0) cv.destroyAllWindows()
相关文章推荐
- OpenCV学习+常用函数记录②:图像卷积与滤波
- CentOS Linux TCP调优需要注意的点
- Nginx实例
- 组件化、模块化、集中式、分布式、服务化、面向服务的架构、微服务架构
- 重磅丨2020向光奖·年度影响力投资人TOP3榜单揭晓
- linux系统中firewalld防火墙管理工具firewall-config(GUI图形用户界面)
- Nginx:负载均衡
- Linux(centos6.8)配置Tomcat环境
- 一、单体架构分析
- Docker知识进阶与容器编排技术
- 白帽子***与网络安全工程师教你:Kali Linux和Windows软件管理的异同【二】
- Java开发必会的Linux命令
- Linux-Iptables/Firewall服务
- Linux-Iptables/Firewall服务
- 大型网站架构演化历程
- 使用udev高效、动态的管理Linux设备文件
- 谈谈nginx和lvs各自的优缺点以及使用
- 白帽子***与网络安全工程师教你:Kali Linux和Windows软件管理的异同【一】
- Linux(Centos6.8)配置Nginx环境
- DevOps心态的5个基本价值