边缘检测 霍夫曼变换 传统图像处理实例

任务:求如下位置交叉点的坐标

在这里插入图片描述

实现效果

在这里插入图片描述

思路:

  1. 通过YOLOv5 检测出目标位置。
  2. 再通过传统图像方法处理。

在这里插入图片描述

传统图像方法的处理思路:

  1. HSV提取红颜色,得到位置X形状的图案。
  2. 二值化处理,得到黑白图像。
  3. 膨胀腐蚀处理,去除噪点,得到干净的图案。
  4. 边缘检测。
  5. 霍夫曼变换,得到许多直线。
  6. 过滤多余直线,得到两条交叉的直线。
  7. 联立方程组得到中心点坐标。

HSV 颜色提取

标志颜色分明,因此用HSV来提取红色区域。使用网站来提取图片颜色所在的色调,饱和度和明度。
http://color.lukas-stratmann.com/color-systems/hsv.html
在这里插入图片描述
也可以写个小脚本通过鼠标来获取图像的HSV。

    def get_hsv_value(self, data_path):
        def getpos(event, x, y, flags, param):
            if event == cv2.EVENT_LBUTTONDOWN:  # 定义一个鼠标左键按下去的事件
                print(HSV[y, x])

        for img_name in os.listdir(data_path):
            img_path = os.path.join(data_path, img_name)
            image = cv2.imread(img_path)
            image = cv2.resize(image, (960, 960))
            HSV = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)

            cv2.imshow("imageHSV", HSV)
            cv2.imshow('image', image)
            cv2.setMouseCallback("imageHSV", getpos)
            cv2.waitKey(0)

            cv2.setMouseCallback("image", getpos)
            cv2.waitKey(0)

如下图,第二幅即为通过HSV提取的图像。
在这里插入图片描述

二值化处理

得到第三幅图像。

def RGB2Black(self, img, thresh=80):
    thresh = 10
    # assign blue channel to zeros
    gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    img = cv2.threshold(gray_img, thresh, 255, cv2.THRESH_BINARY)[1]
    return img

膨胀腐蚀

通过两次膨胀操作和一次腐蚀操作得到最后一张图像,这个主要根据图像的实际情况调整。膨胀腐蚀操作通常是为了去除噪点,得到干净清晰的轮廓。

def dilate_img(self, img):
    kernel = np.ones((5, 5), np.uint8)
    img = cv2.dilate(img, kernel, iterations=1)
    return img

def erode_img(self, img):
    kernel = np.ones((5, 5), np.uint8)
    img = cv2.erode(img, kernel, iterations=1)
    return img

边缘检测 霍夫曼变换

下面对Canny和HoughLines方法的参数做一点解读。

cv2.Canny

  1. image 为 8 位输入图像。
  2. threshold1 表示处理过程中的第一个阈值。
  3. threshold2 表示处理过程中的第二个阈值。

第2,3个参数越小,那么获取得到的细节信息就越丰富。

cv2.HoughLines

  1. image 为 8 位输入图像。
  2. 第二个和第三个参数分别是rho 和theta的精度。
  3. 第四个参数是线长阈值。
dst = cv2.Canny(src, 50, 200, None, 3)

cdst = cv2.cvtColor(dst, cv2.COLOR_GRAY2BGR)

lines = cv2.HoughLines(dst, 1, np.pi / 180, 80, None, 0, 0)

多余线过滤

过滤条件

  1. 角度小于10度。
  2. 边缘的线条不要,只要中间两条交叉线。
  3. 最后得到的线条如果大于两条,那么不要。
    ##########nhuk#################################### angle inspection
    logger.debug("######################################## angle inspection")
    angle_approve_dict = {
   }
    for i, (pt1, pt2) in enumerate(pts_lines):
        # calculate the distance between the line and the center of the image

        # calculate the angle of the line
        angle = int(math.atan2(pt2[1] - pt1[1], pt2[0] - pt1[0]) * (180 / math.pi))
        if angle_approve_dict == {
   }:
            angle_approve_dict[str(angle)] = [(pt1, pt2)]
        else:
            # if the angle is too close to the previous angle, ignore it
            for an in angle_approve_dict:
                int_an = int(an)
                if abs(angle - int_an) < simi_angle_thres or 180 - abs(angle - int_an) < simi_angle_thres:
                    angle_approve_dict[an].append((pt1, pt2))
                    break
            else:
                angle_approve_dict[str(angle)] = [(pt1, pt2)]
        logger.debug(f"angle_approve_dict:{
     angle_approve_dict}")
    ##########nhuk####################################

    ##########nhuk#################################### get the line with the smallest distance to the center
    angle_approved_dist_max = []
    logger.debug("######################################## dist min after angle inspection")
    for an in angle_approve_dict:
        dist_line2center_list = [get_dist_line2center(center_x, pt1, pt2) for (pt1, pt2) in angle_approve_dict[an]]
        logger.debug("dist_line2center_list:{}".format(dist_line2center_list))
        logger.debug("np.argmin(dist_line2center_list):{}".format(np.argmin(dist_line2center_list)))
        angle_approved_dist_max.append(angle_approve_dict[an][np.argmin(dist_line2center_list)])
    ##########nhuk####################################

    ##########nhuk#################################### remove the line that is too far from the center
    logger.debug("######################################## remove the line that is too far from the center")
    angle_approved_dist_max_2 = angle_approved_dist_max.copy()
    for (pt1, pt2) in angle_approved_dist_max_2:
        logger.debug("##############################")
        if len(angle_approved_dist_max) == 2:
            break
        dist_line2center = get_dist_line2center(center_x, pt1, pt2)
        if dist_line2center > center_radius_thres:
            del angle_approved_dist_max[angle_approved_dist_max.index((pt1, pt2))]
        logger.debug(f"pt1:{
     pt1}")
        logger.debug(f"pt2:{
     pt2}")
        logger
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值