霍夫变换手动实现

霍夫变换在直线和圆检测中的应用。

霍夫线变换是通过转换到极坐标空间去寻找最值直线,通过θ和r 的极坐标点唯一确定一条在x-y坐标下的一条直线。

霍夫圆变换的存在一个三维数组(a,b,r)用来唯一确定原始空间的一个确定的圆,在手动实现的过程中发现非并行计算的情况下计算效率极低。

为了降低计算量,考虑降低图像的尺寸以获取计算上的便利,得到圆的指定位置后在重新放缩到原始的图像大小,以达到快速计算的目的。

霍夫圆变换:

import numpy as np
import math
import cv2
from copy import deepcopy
import sys

def hough_circles(edge_image, edge_thresh, radius_values):
    h = edge_image.shape[0]
    w = edge_image.shape[1]
    # print(h,w)
    edgimg = np.zeros((h, w), np.int64)
    for i in range(h):
        for j in range(w):
            if edge_image[i][j] > edge_thresh:
                edgimg[i][j] = 255
            else:
                edgimg[i][j] = 0
    accum_array = np.zeros((len(radius_values), h, w))

    for i in range(h):
        print('Hough Transform进度:', i, '/', h)
        for j in range(w):
            if edgimg[i][j] != 0:
                for r in range(len(radius_values)):
                    rr = radius_values[r]
                    hdown = max(0, i - rr)
                    for a in range(hdown, i):
                        b = round(j+math.sqrt(rr*rr - (a - i) * (a - i)))
                        if b>=0 and b<=w-1:
                            accum_array[r][a][b] += 1
                            if 2 * i - a >= 0 and 2 * i - a <= h - 1:
                                accum_array[r][2 * i - a][b] += 1
                        if 2 * j - b >= 0 and 2 * j - b <= w - 1:
                            accum_array[r][a][2 * j - b] += 1
                        if 2 * i - a >= 0 and 2 * i - a <= h - 1 and 2 * j - b >= 0 and 2 * j - b <= w - 1:
                            accum_array[r][2 * i - a][2 * j - b] += 1
    return edgimg, accum_array

def find_circles(image, accum_array, radius_values, hough_thresh, rescale_factor,H,W):
    returnlist = []
    hlist = []
    wlist = []
    rlist = []
    returnimg = deepcopy(image)
    for r in range(accum_array.shape[0]):
        print('Find Circles 进度:', r, '/', accum_array.shape[0])
        for h in range(accum_array.shape[1]):
            for w in range(accum_array.shape[2]):
                if accum_array[r][h][w] > hough_thresh:
 
                    tmp = 0
                    for i in range(len(hlist)):
                        if abs(w-wlist[i])<10 and abs(h-hlist[i])<10:
                            tmp = 1
                            break
                    if tmp == 0:

                        rr = radius_values[r]
                        flag = '(h,w,r)is:(' + str(h) + ',' + str(w) + ',' + str(rr) + ')'
                        returnlist.append(flag)
                        hlist.append(h)
                        wlist.append(w)
                        rlist.append(rr)
 
    print('圆的数量:', len(hlist))
 
    for i in range(len(hlist)):
        center = (wlist[i], hlist[i])
        rr = rlist[i]
 
        color = (0, 255, 0)
        thickness = 2
        
        rescale_center=(center[0]*rescale_factor,center[1]*rescale_factor)

        rr = rr * rescale_factor
        cv2.circle(returnimg, rescale_center, rr, color, thickness)
 
    return returnlist, returnimg

def main(argv):
    img_name = argv[0]
    image_read = cv2.imread('test2.jpg', cv2.COLOR_BGR2GRAY)
    H,W,C=image_read.shape
    
    #super params
    thresh = 254
    radius_values = []
    for i in range(10):
        radius_values.append(45 + i)
    rescale_factor = 5
    #super params
    
    img = cv2.resize(image_read,(H//rescale_factor,W//rescale_factor))
    gray_image = img

    img1 = cv2.medianBlur(gray_image,21)
    img1 = cv2.Canny(img1,40,100)
    cv2.imwrite('output/' + img_name + "_after_edging.png", img1)

    edgeimg, accum_array = hough_circles(img1, thresh, radius_values)
    
    cv2.imwrite('output/' + img_name + "_after_circle_fitting.png", edgeimg)
    
    # Findcircle
    hough_thresh = 35
    resultlist, resultimg = find_circles(image_read, accum_array, radius_values, hough_thresh,rescale_factor,H,W)
 
    print(resultlist)
    cv2.imwrite('output/' + img_name + "_circles.png", resultimg)
 
 
if __name__ == '__main__':
    sys.argv.append("test")
    main(sys.argv[1:])

霍夫线变换

import numpy as np
import cv2
import math

def hough_line(edge_image, theta_resolution=1.0, rho_resolution=1.0):
    # 得到图像的尺寸
    height, width = edge_image.shape
    # 计算霍夫空间的最大半径
    diag_len = int(math.sqrt(width**2 + height**2))
    # 创建霍夫空间
    hough_space = np.zeros((int(180/theta_resolution), int(2*diag_len/rho_resolution)), dtype=np.uint64)
    
    # 遍历图像中的每个边缘点
    for y in range(height):
        for x in range(width):
            # 如果该点是边缘点
            if edge_image[y, x] != 0:
                # 遍历所有可能的角度
                for theta in range(0, 180, int(theta_resolution)):
                    # 计算对应的半径
                    rho = int(x * math.cos(math.radians(theta)) + y * math.sin(math.radians(theta)))
                    # 在霍夫空间中累加
                    hough_space[theta, rho + diag_len] += 1
    hough_space = hough_space
    return hough_space

# 读取图像并转换为灰度
image = cv2.imread('test2.jpg', cv2.IMREAD_GRAYSCALE)

# 使用Canny边缘检测器
edges = cv2.Canny(image, 40, 100)

# 应用霍夫线变换
hough_space = hough_line(edges)

# 找到霍夫空间中的局部最大值
lines = []
max_lines = 1000  # 检测的最大直线数量
threshold = 75  # 阈值
for rho_idx in range(hough_space.shape[1]):
    for theta_idx in range(hough_space.shape[0]):
        if hough_space[theta_idx, rho_idx] > threshold:
            # 计算直线的参数
            rho = (rho_idx - hough_space.shape[1] // 2) * 1.0
            theta = theta_idx * 1.0
            lines.append((rho, theta))
            # 减少阈值以避免检测到相近的直线
            hough_space[theta_idx, rho_idx] = 0
            max_lines -= 1
            if max_lines <= 0:
                break
    if max_lines <= 0:
        break

# 绘制检测到的直线
image_out = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)
for rho, theta in lines:

    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))
    cv2.line(image_out,(x1,y1),(x2,y2),(0,0,255),2)
# 显示结果
def norm(x):
    return ( (x-x.min())/(x.max()-x.min()) )*255

hough_space = hough_space.astype(np.uint8).transpose(1,0)
hough_space = cv2.resize(hough_space.astype(np.uint8),(720,720))
cv2.imshow('Original Image', image)
cv2.imshow('Canny Image', edges)
cv2.imshow('Hough Space', (hough_space) )
cv2.imshow('Hough Line Detection', image_out)
cv2.waitKey(0)
cv2.destroyAllWindows()
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值