OpenCV与图像处理(四)

2020-07-28 11:38:14 浏览数 (1)

本章节的主要内容是霍夫变换,包括以下2个知识点:

1、直线检测

2、圆检测

以下代码均在python3.6,opencv4.2.0环境下试了跑一遍,可直接运行。


1、霍夫变换介绍

霍夫变换(Hough Transform)是图像处理中的一种特征提取技术,该过程在一个參数空间中通过计算累计结果的局部最大值得到一个符合该特定形状的集合作为霍夫变换结果。

如果可以用数学形式表示形状,则霍夫变换是一种检测任何形状的流行技术。即使形状有些破损或变形,也可以检测出形状。

图像霍夫变换通过把图像的坐标从2D平面坐标系变换到极坐标空间,可以发现原来在平面坐标难以提取的几何特征信息(如:直线、圆等),图像的直线与圆检测就是典型的利用霍夫空间特性实现二值图像几何分析的例子。

2、霍夫线变换

1)标准的霍夫变换:cv2.HoughLines()

2)霍夫变换直线概率:cv2.HoughLinesP()

概率霍夫变换是霍夫变换的优化,它没有考虑所有要点,取而代之的是仅采用随机的点子集,进行线检测,须降低阈值。

cv2.HoughLinesP()有两个新的参数:

(1)minLineLength - 最小行长。小于此长度的线段将被拒绝。

(2)maxLineGap - 线段之间允许将它们视为一条线的最大间隙。

代码实战:

代码语言:javascript复制
# -*- coding: utf-8 -*-
import cv2
import numpy as np

# 标准的霍夫直线变换
def HoughLines_detection(img):
    gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
    edges = cv2.Canny(gray, 50, 150, apertureSize=3)  #apertureSize参数默认其实就是3
    cv2.imshow("edges", edges)
    lines = cv2.HoughLines(edges, 1, np.pi/180, 80)
    for line in lines:
        rho, theta = line[0]  #line[0]存储的是点到直线的极径和极角,其中极角是弧度表示的。
        a = np.cos(theta)   #theta是弧度
        b = np.sin(theta)
        x0 = a * rho    #代表x = r * cos(theta)
        y0 = b * rho    #代表y = r * sin(theta)
        x1 = int(x0   1000 * (-b)) #计算直线起点横坐标
        y1 = int(y0   1000 * a)    #计算起始起点纵坐标
        x2 = int(x0 - 1000 * (-b)) #计算直线终点横坐标
        y2 = int(y0 - 1000 * a)    #计算直线终点纵坐标   
        # 注:这里的数值1000给出了画出的线段长度范围大小,
        # 数值越小,画出的线段越短,数值越大,画出的线段越长。
        # 点的坐标必须是元组,不能是列表。
        cv2.line(img, (x1, y1), (x2, y2), (255, 0, 255), 2)
    cv2.imshow("HoughLines_img", img)

# 概率霍夫直线变换:标准的霍夫线变换的优化版,也是一种寻找直线检测
def HoughLinesP_detection(img):
    gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
    edges = cv2.Canny(gray, 50, 150, apertureSize=3)  #apertureSize参数默认其实就是3
    cv2.imshow("edges", edges)
    lines = cv2.HoughLinesP(edges, 1, np.pi/180, 60, minLineLength=60, maxLineGap=5)
    for line in lines:
        x1, y1, x2, y2 = line[0]
    # for x1, y1, x2, y2 in lines[0]:
        cv2.line(img, (x1, y1), (x2, y2), (255, 0, 255), 2)
    cv2.imshow("HoughLinesP_img",img)

if __name__ == '__main__':
    img_path = "squares.jpg"
    img=cv2.imread(img_path)
    cv2.imshow('origin', img)
    HoughLines_detection(img)
    HoughLinesP_detection(img)
    cv2.waitKey(0)

运行结果:

原图

边缘检测图

HoughLines图

HoughLinesP图


3、霍夫圆检测:cv2.HoughCircles()

假设平面坐标的任意一个圆上的点C,转换到极坐标中,在点C处有最大值,霍夫变换正是利用这个原理实现圆的检测。

霍夫圆检测对噪声比较敏感,所以首先要对图像做中值滤波,也可用高斯滤波,视噪声类型而定,具体可见图像模糊。

基于效率考虑,Opencv中实现的霍夫变换圆检测是基于图像梯度的实现,分为两步:

(1)检测边缘,发现可能的圆心。

(2)基于第一步的基础上从候选圆心开始计算最佳半径大小。

代码实战:

代码语言:javascript复制
# -*- coding: utf-8 -*-
import cv2
import numpy as np

# 霍夫圆检测
def HoughCircles_detection(img):
    # 边缘保留滤波EPF
    # dst = cv2.pyrMeanShiftFiltering(img, 10, 100)
    # 中值滤波
    dst = cv2.medianBlur(img,5)
    gray = cv2.cvtColor(dst, cv2.COLOR_RGB2GRAY)
    circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 20, param1=50, param2=30, minRadius=0, maxRadius=0)
    # 把circles包含的圆心和半径的值变成整数
    circles = np.uint16(np.around(circles)) 
    for i in circles[0, : ]:
        cv2.circle(img, (i[0], i[1]), i[2], (0, 0, 255), 2)  #画圆
        cv2.circle(img, (i[0], i[1]), 2, (0, 0, 255), 2)  #画圆心
    cv2.imshow("circles", img)

if __name__ == '__main__':
    img_path = "circle3.jpg"
    img=cv2.imread(img_path)
    cv2.imshow('origin', img)
    HoughCircles_detection(img)
    cv2.waitKey(0)

运行结果:

原图

HoughCircles图

以上内容如有错误或者需要补充的,请留言!

0 人点赞