之前的两篇文章讲过利用边缘检测来提取滑块的轮廓,当遇到提取的轮廓有多条时,在去筛选,到最后的效果也不一定很好,所以可以使用另一种方法来检测却缺口,有的滑块,是包含一个小图,和一个大图的,小图是从大图中的一部分抠出来的,这个时候,就可以用到opencv中的模板匹配功能,模板匹配,可以将小图,匹配到大图中缺口的那个区域,这样,也能达到检测滑块缺口的效果,下面来看实战
上述的数据集可能需要注意一下,在你把下图拿下来之后,可以看到,我的小图,上下两边还会有白色的填充区域存在,那么在进行模板匹配之后的效果可能不会很好,所以先要对小图进行一些处理,把小图周围的空白填充区域去掉
# -*- coding: utf-8 -*-
import cv2
import numpy as np
import os
def cv_show(img): # 展示图片
cv2.imshow("img", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 转换颜色通道,保持颜色准确
# image = cv2.imread(r"1_1.jpg")
gap = cv2.imread(r"1_2.jpg")
# image_gray = cv2.cvtColor(image.copy(), cv2.COLOR_BGR2GRAY)
gap_gray = cv2.cvtColor(gap.copy(), cv2.COLOR_BGR2GRAY)
h, w = gap_gray.shape
w_start_index, h_start_index = 0, 0
w_end_index, h_end_index = w, h
# 缺口图去除背景
for i in range(h):
if not any(gap_gray[i, :]):
h_start_index = i
else:
break
for i in range(h - 1, 0, -1):
if not any(gap_gray[i, :]):
h_end_index = i
else:
break
for i in range(w):
if not any(gap_gray[:, i]):
w_start_index = i
else:
break
for i in range(w - 1, 0, -1):
if not any(gap_gray[:, i]):
w_end_index = i
else:
break
# 取出完整的缺口图
gap_gray = gap_gray[h_start_index:h_end_index+1, w_start_index:w_end_index+1]
cv_show(gap_gray)
上述的代码其实意图很明显,循环四次,分别是从上到下,从下到上,从左到右,从右到左,依次循环,当循环到,一行或者一列区域不相同的话,那么就视为已经接近缺口滑块,然后再根据索引进行分割,下面是展示灰度效果图
取出小滑块后,就可以直接使用opencv中的模板匹配功能了,先看完整代码
我的步骤大致是这样,先转为灰度图,然后在对小图进行处理,然后添加自适应阈值化,然后使用边缘检测寻找几乎所有的边缘,在通过用边缘进行模板匹配,找到匹配值可能性最大的缺口即可
# -*- coding: utf-8 -*-
import cv2
import numpy as np
import os
def cv_show(img): # 展示图片
cv2.imshow("img", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 转换颜色通道,保持颜色准确
image = cv2.imread(r"1_1.jpg")
gap = cv2.imread(r"1_2.jpg")
image_gray = cv2.cvtColor(image.copy(), cv2.COLOR_BGR2GRAY)
gap_gray = cv2.cvtColor(gap.copy(), cv2.COLOR_BGR2GRAY)
h, w = gap_gray.shape
w_start_index, h_start_index = 0, 0
w_end_index, h_end_index = w, h
# 缺口图去除背景
for i in range(h):
if not any(gap_gray[i, :]):
h_start_index = i
else:
break
for i in range(h - 1, 0, -1):
if not any(gap_gray[i, :]):
h_end_index = i
else:
break
for i in range(w):
if not any(gap_gray[:, i]):
w_start_index = i
else:
break
for i in range(w - 1, 0, -1):
if not any(gap_gray[:, i]):
w_end_index = i
else:
break
# 取出完整的缺口图
gap_gray = gap_gray[h_start_index:h_end_index+1, w_start_index:w_end_index+1]
image_gray = cv2.adaptiveThreshold(image_gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 5, 0)
gap_gray = cv2.adaptiveThreshold(gap_gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 5, 0)
image_v1 = cv2.Canny(image_gray, 0, 500)
gray_v1 = cv2.Canny(gap_gray, 0, 500)
# cv_show(gray_v1)
result = cv2.matchTemplate(image_v1, gray_v1, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
x, y = max_loc
h, w = gap_gray.shape
result = np.array(image.copy())
color = (0, 0, 255)
# print(check_box)
cv2.rectangle(result, (x, y), (x + w, y + h), color, 2)
# res = np.hstack([image_gray,gray_v1, image_v1, result])
cv_show(result)