主要目的:实现目标物的框选,查找边缘
此处不涉及算子
设置好搜索方法(逆时针)
Direct = [(1, 0), (1, 1), (0, 1), (-1, 1), (-1, 0), (-1, -1), (0, -1), (1, -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()