您的位置:

Opencv霍夫直线检测

一、Opencv霍夫直线检测需要拟合吗

Opencv霍夫直线检测的基本原理是将物体上的曲线或者边缘进行检测和提取。在直线的情况下,原理是将直线的参数进行变换,转换为Hough空间的点,在Hough空间中找出在一定范围内累计值最高的点,通过反演变换,将Hough空间的点映射回到直线上,从而得到直线参数。

在使用Opencv霍夫直线检测时,通常得到的是直线的参数,可以直接使用这些参数进行绘制,而不需要拟合。但是,在某些情况下,直线可能不是完整的,可能存在断点或曲折,这时可以使用拟合的方法将多个线段拟合成一条直线。

下面是一个简单的例子,演示直接绘制霍夫直线检测的结果和拟合后的结果:

import cv2 as cv
import numpy as np

img = cv.imread('image.jpg')
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
edges = cv.Canny(gray,50,150,apertureSize = 3)
lines = cv.HoughLines(edges,1,np.pi/180,200)

# 直接绘制霍夫直线检测的结果
for line in lines:
    rho,theta = line[0]
    a = np.cos(theta)
    b = np.sin(theta)
    x0 = a*rho
    y0 = b*rho
    x1 = int(x0 + 1000*(-b))
    y1 = int(y0 + 1000*(a))
    x2 = int(x0 - 1000*(-b))
    y2 = int(y0 - 1000*(a))
    cv.line(img,(x1,y1),(x2,y2),(0,0,255),2)

# 拟合结果
lines = cv.HoughLinesP(edges,1,np.pi/180,100,minLineLength=100,maxLineGap=10)
for line in lines:
    x1,y1,x2,y2 = line[0]
    cv.line(img,(x1,y1),(x2,y2),(0,255,0),2)

cv.imshow('img',img)
cv.waitKey(0)
cv.destroyAllWindows()

二、Opencv霍夫变换检测矩形

除了检测直线,Opencv霍夫变换还可以用于检测矩形。对于矩形检测,我们可以使用霍夫变换的概率式算法,通过调整参数来检测出符合条件的矩形。

下面是一个简单的例子,演示Opencv霍夫变换用于检测矩形的结果:

import cv2 as cv
import numpy as np

img = cv.imread('image.jpg')
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
edges = cv.Canny(gray,50,150,apertureSize = 3)
lines = cv.HoughLinesP(edges,1,np.pi/180,20,minLineLength=30,maxLineGap=10)

# 转换为霍夫坐标系
for i in range(lines.shape[0]):
    line = lines[i][0]
    x1,y1,x2,y2 = line
    cv.line(img,(x1,y1),(x2,y2),(0,0,255),1,cv.LINE_AA)

# 检测矩形
contours, hierarchy = cv.findContours(edges, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)

for i in range(len(contours)):
    cnt = contours[i]
    area = cv.contourArea(cnt)
    if area < 500 or area > 10000:
        continue
    rect = cv.minAreaRect(cnt)
    box = cv.boxPoints(rect)
    box = np.int0(box)
    cv.drawContours(img,[box],0,(0,255,0),2)

cv.imshow('img',img)
cv.waitKey(0)
cv.destroyAllWindows()

三、Opencv检测直线选取

在Opencv霍夫直线检测中,由于图像中的直线可能会非常多,因此我们需要对直线进行筛选和选取,以便于我们更加有效地分析和处理图像。

在直线的筛选中,可以根据直线的长度、角度、距离等特征进行筛选,只保留符合条件的直线。在选取直线时,可以根据直线的位置、长度、交叉情况等因素进行选择,以便于我们更好地分析图像的特征。

下面是一个简单的例子,演示如何对直线进行筛选和选取:

import cv2 as cv
import numpy as np

img = cv.imread('image.jpg')
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
edges = cv.Canny(gray,50,150,apertureSize = 3)
lines = cv.HoughLinesP(edges,1,np.pi/180,20,minLineLength=30,maxLineGap=10)

# 直线的筛选和选取
h,w = img.shape[:2]
lineInfoList = []
for i in range(lines.shape[0]):
    line = lines[i][0]
    x1,y1,x2,y2 = line

    # 直线长度筛选
    length = np.sqrt((x1-x2)**2 + (y1-y2)**2)
    if length < 50:
        continue
    # 直线角度筛选
    angle = np.arctan2(y2-y1, x2-x1) * 180.0 / np.pi
    if angle < -10 or angle > 10:
        continue
    # 直线距离筛选
    distance = abs(x1-x2) + abs(y1-y2)
    if distance > 0.2*w:
        continue

    # 记录直线信息
    lineInfoList.append((x1,y1,x2,y2))

# 直线的选取
for i in range(len(lineInfoList)):
    for j in range(i+1, len(lineInfoList)):
        x1,y1,x2,y2 = lineInfoList[i]
        x3,y3,x4,y4 = lineInfoList[j]
        # 交叉情况筛选
        if (abs(x1-x3) + abs(y1-y3) + abs(x2-x4) + abs(y2-y4)) > (abs(x1-x4) + abs(y1-y4) + abs(x2-x3) + abs(y2-y3)):
            continue
        # 直线长度筛选
        length1 = np.sqrt((x1-x2)**2 + (y1-y2)**2)
        length2 = np.sqrt((x3-x4)**2 + (y3-y4)**2)
        if length1 < 50 or length2 < 50:
            continue

        # 绘制选中的直线
        cv.line(img,(x1,y1),(x2,y2),(0,0,255),2)
        cv.line(img,(x3,y3),(x4,y4),(0,0,255),2)

cv.imshow('img',img)
cv.waitKey(0)
cv.destroyAllWindows()