图像处理——边缘跟踪算法(Python)

边缘追踪算法

主要目的:实现目标物的框选,查找边缘
此处不涉及算子

处理步骤:

  1. 图像灰度化
  2. 图像二值化(处理好阈值——可优化,此处不涉及该研究)
  3. 找到起始点
  4. 从起始点开始边缘跟踪

算法核心:

设置好搜索方法(逆时针)

Direct = [(1, 0), (1, 1), (0, 1), (-1, 1), (-1, 0), (-1, -1), (0, -1), (1, -1)]

图像处理——边缘跟踪算法(Python)_第1张图片
第一次搜索按照初始点的方向进行,这里需要清楚的是,获取初始点方向的方法

关于初始点的获取

  可以采取从左到右从上到下等方式,即获取的初始点必须是目标图像的顶点(上、下、左、右)
  不同的方向寻找的起点会使后面的搜索方法不同
  使用temp来作为方向的指示(数字代表的方向见上图中的黄色数字指示)
  这里使用查找方法为从上到下,从左到右,这里获取的是目标的左上角的点
  (使用上面的方法)令temp初始化:temp = 5 。通过起点的查找可以清楚的是目标物的左上方不存在目标物,因此最可能出现的点在左下方。顾为5。

关于搜索

  采用逆时针的循序,我们通过数字可以发现规律
  当temp = 5时,假设存在,即当前边缘中心(x,y)移动到temp= 5的方向,即初始(x,y) = (0,0),移动 ——> (x,y) = (-1,-1)
  我们向下一个点移动的时候相当于夹了一个180度的角,此时再进行搜索的时候需要回转90°,即变化temp的值。
  对此我们可以总结一条公式:
  当 temp 为 偶数 的时候:
     temp(new) = (temp + 7)% 8
  当 temp 为 奇数 的时候:
     temp(new) = (temp + 6)% 8

对于包围图像和非包围图像的提醒:

  在控制结束条件的时候需要注意的一点就是,包围图像的收尾为同一点,即当(x,y) = (startx, starty)时结束
  但当图像非包围图像时,需要控制条件进行,并且当图像进行分割时,左右两边可能需要再进行搜索,此处只拿特例,后续有更优化算法再更新。

# -*- coding = utf-8 -*-
# @Time : 2022/2/24 17:00
# @Author : Vinci
# @File : borad_find.py
# @Software: PyCharm

import cv2 as cv
import numpy as np


def get_binary_img(timg):
    bin_img = np.zeros(shape=timg.shape, dtype=np.uint8)
    h = timg.shape[0]  # 表示y的大小
    w = timg.shape[1]  # 表示x的大小
    # print(" h = {} w = {}".format(h,w))
    for i in range(h):  # 从上到下
        for j in range(w):
            bin_img[i][j] = 255 if timg[i][j] > 200 else 0
    return bin_img


def get_left_up_start_pt(flag, bin_img):
    h = bin_img.shape[0]
    w = bin_img.shape[1]
    find = 0
    start_y = 0
    start_x = 0
    if flag == 0:
        for j in range(h):  #从上到下
            for i in range(w):
                if bin_img[j][i] == 0:
                    find = 1
                    start_y = j
                    start_x = i
                    break
            if find == 1:
                break
    else:
        for j in range(h - 1, -1, -1):
            for i in range(w - 1, -1, -1):
                if bin_img[j][i] == 0:
                    find = 1
                    start_y = j
                    start_x = i
                    break
            if find == 1:
                break
    return find, start_x, start_y


def trace_contour(bin_img, find, start_i, start_j, contour_img):
    """
        物体(黑色) 为0
        背景(白色) 为255
    """
    flag = 0
    if find:
        contour_img[start_i][start_j] = 0

    Direct = [(1, 0), (1, 1), (0, 1), (-1, 1), (-1, 0), (-1, -1), (0, -1), (1, -1)]
    temp = 5
    if find == 2:
        temp = 1
    x, y = start_i, start_j
    while True:
        while True:
            tx = x + Direct[temp][1]
            ty = y + Direct[temp][0]
            if tx > bin_img.shape[1] - 1 or ty > bin_img.shape[0] - 1 or tx < 0 or ty < 0:
                temp += 1
                if temp == 8:
                    temp = 0
                continue
            if bin_img[ty][tx] == 0:
                contour_img[ty][tx] = 0
                if temp % 2 == 0:
                    temp = (temp + 7) % 8
                else:
                    temp = (temp + 6) % 8
                x = tx
                y = ty
                break
            temp += 1
            if temp == 8:
                temp = 0
        # print(x, y)
        if start_i == x and start_j == y:
            return flag, contour_img
        if x >= bin_img.shape[1] - 1 or y >= bin_img.shape[0] - 1 or x <= 0 or y <= 0:
            flag = 1
            return flag, contour_img


if __name__ == "__main__":
    img_name = "img/cap.png"
    img = cv.imread(img_name)
    gray_img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)  # 转灰度图
    bin_img = get_binary_img(gray_img)  # 二值化

    # print(bin_img[370][360])   #需要注意的是图像转为数组的时候 x,y是反过来的
    # 边界追踪
    flag1 = 0
    find, start_i, start_j = get_left_up_start_pt(flag1, bin_img)
    # cv.circle(bin_img, (start_i, start_j), 3, (0, 0, 0), -1)
    # print("start_x, start_y = ", start_i, start_j)
    # cv.imshow("1", bin_img)

    contour_img = np.zeros(shape=bin_img.shape, dtype=np.uint8)
    contour_img += 255
    flag2, contour_img = trace_contour(bin_img, find, start_i, start_j, contour_img)

    if flag2 == 1:
        find1, start_i1, start_j1 = get_left_up_start_pt(flag2, bin_img)
        f, contour_img = trace_contour(bin_img, find1 + 1, start_i1, start_j1, contour_img)
        contour_img[0] = 255
        contour_img[len(contour_img) - 1] = 255
        for w in range(len(contour_img)):
            contour_img[w][0] = 255
            contour_img[w][len(contour_img[0]) - 1] = 255
    cv.imshow("img", contour_img)
    cv.waitKey()
    cv.destroyAllWindows()

图像处理——边缘跟踪算法(Python)_第2张图片
图像处理——边缘跟踪算法(Python)_第3张图片

你可能感兴趣的:(图像处理,算法,图像处理,python)