先回顧一下膨脹腐蝕的定義
dilate 膨脹
膨脹過程:B首先做關於原點的映射B^,然後平移x。A被B的膨脹是被所有x平移後與A至少有一個非零公共元素。
erode 腐蝕
也就是說A被B的腐蝕的結果爲所有使B被x平移後包含於A的點x的集合。
注意:圖中中心點也有個點,其實由此可以推出HMT:
當把三角形看做A時把上圖A則爲,上圖結構元B則是B1的補集B2,則上圖可以表示爲
,而
的結果中A的中心點保留,則兩個交集爲B在A中的匹配,記爲:
HMT
這幅圖更爲清楚:
讓每個圖形的原點位於它的重心。如果用一個小窗口W包含X,X關於W的本地背景是圖(b)中的集合差(W-X)。圖©爲集合A的補。圖(d)示出A被X腐蝕的結果。A被X的腐蝕在X中只有X的原點,這樣X才能完全包含於A。圖(e)表示集合A的補被本地背景集合(W-X)的腐蝕;外圍陰影區域也是腐蝕結果的一部分。
實現
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2019/11/23 12:39
# @Author : ZhigangJiang
# @File : mian.py
# @Software: PyCharm
# @Description:hit and miss translate
import cv2
import matplotlib.pyplot as plt
import numpy as np
def plt_show_opcv(title, image):
if image.shape.__len__() == 3:
plt.imshow(image[:, :, ::-1])
else:
plt.imshow(image, cmap='gray')
plt.title(title)
plt.show()
def pme(titles, images, rc=None):
row = None
col = None
if rc is None:
length = titles.__len__()
row = int(np.sqrt(length))
col = int(length / row)
if length - row - col > 0:
row += 1
else:
row = rc[0]
col = rc[1]
for i in range(titles.__len__()):
plt.subplot(row, col, i + 1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]), plt.yticks([i])
plt.show()
def hmt(a, b):
b1 = ~b
b2 = b
a1 = ~a
a2 = a
pme(["b1", "b2", "x1", "x2"],
[b1, b2, a1, a2])
x1_erode_b1 = cv2.erode(a1, b1)
x2_erode_b2 = cv2.erode(a2, b2)
plt_show_opcv("a1_erode_b1", x1_erode_b1)
plt_show_opcv("a1_erode_b1_", cv2.dilate(x1_erode_b1, np.ones((10, 10), np.uint8)))
plt_show_opcv("a2_erode_b2", x2_erode_b2)
plt_show_opcv("a2_erode_b2_", cv2.dilate(x2_erode_b2, np.ones((10, 10), np.uint8)))
r = cv2.bitwise_and(x1_erode_b1, x2_erode_b2)
return r
image_X = cv2.imread("images/X.png", 0)
image_B = cv2.imread("images/B_triangle.png", 0)
ret1, image_X = cv2.threshold(image_X, 127, 255, cv2.THRESH_BINARY)
ret2, image_B = cv2.threshold(image_B, 127, 255, cv2.THRESH_BINARY)
plt_show_opcv("X", image_X)
plt_show_opcv("B", image_B)
re = hmt(image_X, image_B)
targets = []
for i in range(re.shape[0]):
for j in range(re.shape[1]):
if re[i][j]:
targets.append((j, i))
print(i, j)
for target in targets:
image_X = cv2.drawMarker(image_X, target, 125, markerType=cv2.MARKER_CROSS, markerSize=20, thickness=3)
plt_show_opcv("re", image_X)
結果
三角形只擊中兩個,說明左下角的被影響到了,說明這種方法識別擊中的是與結構元完全相同的圖像
複雜圖形
中文
字母識別
單詞識別,左下角learning沒有被識別到,因爲在截圖產生了噪聲,雖然進行了閾值處理,但是還是有誤差。
所以,用這種識別單詞只是在理想情況下可行。