首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >多模板与Scikit图像的匹配

多模板与Scikit图像的匹配
EN

Stack Overflow用户
提问于 2022-03-28 18:17:18
回答 1查看 515关注 0票数 0

我想找到硬币的中间,找到弧度。半径可以告诉我硬币是5美分还是50美分。在找到图像后,我必须能够检测到圆圈的中间位置,这样我才能给它们颜色。

我已经开始为Hough-transform编写代码了

希望有人能帮我解决这个问题。

hough变换代码:

代码语言:javascript
复制
image = img_as_ubyte(image)
edges = feature.canny(image, sigma=1.5, low_threshold=10, high_threshold=25)

# Detect two radii
hough_radii = np.arange(17, 35, 2)
hough_res = hough_circle(edges, hough_radii)

# Select the 11 coins
accums, cx, cy, radii = hough_circle_peaks(hough_res, hough_radii,total_num_peaks=11)

# Draw them
fig, ax = plt.subplots(ncols=1, nrows=1, figsize=(10, 4))
image = color.gray2rgb(image)
count = 0
for center_y, center_x, radius in zip(cy, cx, radii):
    circy, circx = circle_perimeter(center_y, center_x, radius,
                                    shape=image.shape)
    image[circy, circx] = (220, 20, 20)
    count += 1


ax.imshow(image)
plt.figure(figsize=(25,25))
print("In this image we can detect", count, "coins")
plt.show()
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-03-28 23:07:37

你有两个选择来找到匹配的圆圈。

第一个:滑动窗口

较小的窗口是你在输入图像中寻找的模板,这里有两个不同半径分别为19和21的图像。首先,找出模板和输入图像的边缘,然后将裁剪的部分图像与模板相乘。每个接近模板的区域都应该具有更高的值。

代码语言:javascript
复制
def correlation_coefficient(patch1, patch2):
    product = np.mean((patch1 - patch1.mean()) * (patch2 - patch2.mean()))
    stds = patch1.std() * patch2.std()
    if stds == 0:
        return 0
    else:
        product /= stds
        return product


im1 =  cv2.imread("Original.jpg")
im1 = cv2.cvtColor(np.float32(im1), cv2.COLOR_BGR2GRAY)


im2 = cv2.imread("bigger.png")
im2 = cv2.cvtColor(np.float32(im2), cv2.COLOR_BGR2GRAY)


sh_row, sh_col = im1.shape
correlation = np.zeros_like(im1)

for i in range(sh_row - im2.shape[1]):
    for j in range(sh_col - im2.shape[0]):
        temp1 = im1[i : i + im2.shape[1], j : j + im2.shape[0]]
        if(temp1.shape != im2.shape):
          correlation[i, j] = 0
          continue
        correlation[i, j] = correlation_coefficient(temp1, im2)


fig = plt.figure(figsize=(10, 7))
plt.imshow(correlation, cmap=plt.cm.gray)
plt.show()

这里的模板是小的或大的。更大的输出是

正如你所看到的,一些点被突出显示为圆心。或者使用第二次匹配计算:

代码语言:javascript
复制
im1 =  cv2.imread("Original.jpg")
im1 = cv2.cvtColor(np.float32(im1), cv2.COLOR_BGR2GRAY)

im1 = canny(im1, sigma=3, low_threshold=5, high_threshold=40)
im1 = im1.astype(np.uint8)

im2 = cv2.imread("bigger.png")
im2 = cv2.cvtColor(np.float32(im2), cv2.COLOR_BGR2GRAY)

im2 = canny(im2, sigma=3, low_threshold=5, high_threshold=40)
im2 = im2.astype(np.uint8)
sh_row, sh_col = im1.shape

d = 1

correlation = np.zeros_like(im1)

for i in range(sh_row - im2.shape[1]):
    for j in range(sh_col - im2.shape[0]):
        temp1 = im1[i : i + im2.shape[1], j : j + im2.shape[0]]
        if(temp1.shape != im2.shape):
          correlation[i, j] = 0
          continue
        correlation[i, j] = np.sum(np.multiply(temp1, im2))

io.imshow(correlation, cmap='gray')
io.show()

此外,我们也有同样的结果:

第一种方法不能帮助我们找到指定的圆。因为您需要为两个模板设置一个阈值,并解决越来越多的挑战。让我们研究另一种方法。

第一种: Hough变换

首先,运行精明的边缘检测器,然后找到半径范围从1到100的所有圆。然后删除近圆(中心彼此相近的圆圈):

代码语言:javascript
复制
import numpy as np
import matplotlib.pyplot as plt
import cv2
from skimage import data, color
from skimage.transform import hough_circle, hough_circle_peaks
from skimage.feature import canny
from skimage.draw import circle_perimeter
from skimage.util import img_as_ubyte
from skimage import io, feature
from scipy import ndimage
import imutils
from scipy import signal
from skimage import io, feature



image = cv2.imread("Original.jpg")
fig = plt.figure(figsize=(10, 7))

fig.add_subplot(1, 2, 1)
plt.imshow(image)
plt.axis('off')
plt.title("Original Image")

image = cv2.cvtColor(np.float32(image), cv2.COLOR_BGR2GRAY)
edges = canny(image, sigma=3, low_threshold=5, high_threshold=40)

fig.add_subplot(1, 2, 2)
plt.imshow(edges, cmap=plt.cm.gray)
plt.axis('off')
plt.title("After Run Canny Edge Detector")

# which raddii?
hough_radii = np.arange(1, 100)
hough_res = hough_circle(edges, hough_radii)

accums, cx, cy, radii = hough_circle_peaks(hough_res, hough_radii, total_num_peaks=100)
output = np.column_stack((cx, cy, radii))
output = output[(output[:,2] > 10)]

output = output[np.argsort(output[:, 1])]
output = output[np.argsort(output[:, 0])]

print(f"Circles Before Edit")
print(f"cx={output[:,0]}")
print(f"cy={output[:,1]}")
print(f"radii={output[:,2]}")

index = 0
flag = False
while (index < output.shape[0] - 1):

  if(abs (output[index][0] - output[index+1][0]) < 5 ):
    if(abs (output[index][1] - output[index+1][1]) < 5 ):
      # print(f"del index {index+1}")
      output = np.delete(output, (index+1), axis=0)
      flag = True
    else:
      flag = False
  else:
    flag = False
  if(flag is not True):
    index += 1
print(f"Circles After Edit")
print(f"cx={output[:,0]}")
print(f"cy={output[:,1]}")
print(f"radii={output[:,2]}")


plt.show()


red = output[(output[:,2] <= 20)]
print(f"Red Circles")
print(f"cx={red[:,0]}")
print(f"cy={red[:,1]}")
print(f"radii={red[:,2]}")

green = output[(output[:,2] >= 20)]
print(f"Green Circles")
print(f"cx={green[:,0]}")
print(f"cy={green[:,1]}")
print(f"radii={green[:,2]}")

检查结果:

代码语言:javascript
复制
Circles Before Edit
cx=[ 96  96  97  98 105 106 146 165 188 189 196 196 202 203 204 216 264 265]
cy=[137 138 136 138 232 232 356 229 102 102 166 166 222 221 286 322 116 116]
radii=[22 23 23 21 22 21 19 21 21 22 19 18 19 18 22 19 18 19]
Circles After Edit
cx=[ 96 105 146 165 188 196 202 204 216 264]
cy=[137 232 356 229 102 166 222 286 322 116]
radii=[22 22 19 21 21 19 19 22 19 18]

在进行了所有必要的计算之后:

代码语言:javascript
复制
Red Circles
cx=[146 196 202 216 264]
cy=[356 166 222 322 116]
radii=[19 19 19 19 18]
Green Circles
cx=[ 96 105 165 188 204]
cy=[137 232 229 102 286]
radii=[22 22 21 21 22]

结果表明,5圈被提出为red5圆圈被推荐为green

Update#1

在对这些问题进行预处理之前要小心。这些处理包括侵蚀、膨胀和中值滤波改变圆圈半径。

绘图圈

输入半径分别为19和21,因此大于20的半径属于绿色,小于20的半径属于红色。为了简单起见,我将黄色设置为radius = 20。在最后一步中,您应该删除丰富的圆圈。贝娄,我把他们都聚集在一起:

代码语言:javascript
复制
def remove_redundance(output):
  
  print(f"output.shape={output.shape}")
  index = 0
  del_first = False
  index_first = 0
  while (index_first < output.shape[0]):
    index_second = index_first + 1
    del_second = False
    while (index_second < output.shape[0]):

      if( (abs(output[index_first][0] - output[index_second][0]) < 10) and 
         (abs(output[index_first][1] - output[index_second][1]) < 10) ):
        
        if(output[index_first][3] > output[index_second][3]):
          output = np.delete(output, (index_second), axis=0)
          del_second = True
        else:
          output = np.delete(output, (index_first), axis=0)
          del_first = True
          break

      else:
        del_second = False
        del_first = False

      if (del_second == False):
        index_second += 1
    
    
    if (del_first == False):
      index_first += 1
    else:
      del_first = False

  print(f"output.shape={output.shape}")
  return output
  

def draw_circles(circle, coordinate, green = 0):
  for cx, cy, radii in zip(coordinate[:,0], coordinate[:,1], coordinate[:,2]):
    # Center coordinates
    center_coordinates = (int(cx), int(cy))
    
    # Radius of circle
    radius = int(radii)
    
    if(green == 1):
      color = (0, 255, 0)
    elif(green == 0):
      color = (0, 0, 255)
    elif(green == -1):
      color = (0, 255, 255)
      
    thickness = 1#-1
      
    circle = cv2.circle(circle, center_coordinates, radius, color, thickness)

  return circle



image = cv2.imread("Original.jpg")
# image = cv2.medianBlur(image, 3)
fig = plt.figure(figsize=(10, 7))

fig.add_subplot(1, 2, 1)
plt.imshow(image)
plt.axis('off')
plt.title("Original Image")

image = cv2.cvtColor(np.float32(image), cv2.COLOR_BGR2GRAY)
edges = canny(image, sigma=3, low_threshold=5, high_threshold=40)

fig.add_subplot(1, 2, 2)
plt.imshow(edges, cmap=plt.cm.gray)
plt.axis('off')
plt.title("After Run Canny Edge Detector")

# which raddii?
hough_radii = np.arange(1, 500)
hough_res = hough_circle(edges, hough_radii)

accums, cx, cy, radii = hough_circle_peaks(hough_res, hough_radii, total_num_peaks=500)
output = np.column_stack((cx, cy, radii, accums))#
output = output[(output[:,2] > 10)]

output = output[np.argsort(output[:, 1])]
output = output[np.argsort(output[:, 0])]

print(f"Circles Before Edit")
print(f"cx={output[:,0]}")
print(f"cy={output[:,1]}")
print(f"radii={output[:,2]}")


output = remove_redundance(output)


print(f"Circles After Edit")
print(f"cx={output[:,0]}")
print(f"cy={output[:,1]}")
print(f"radii={output[:,2]}")


plt.show()


red = output[(output[:,2] < 20)]
if(red.shape[0]>0):
  print(f"Red Circles")
  print(f"cx={red[:,0]}")
  print(f"cy={red[:,1]}")
  print(f"radii={red[:,2]}")

green = output[(output[:,2] > 20)]
if(green.shape[0]>0):
  print(f"Green Circles")
  print(f"cx={green[:,0]}")
  print(f"cy={green[:,1]}")
  print(f"radii={green[:,2]}")


yellow = output[(output[:,2] == 20)]
if(yellow.shape[0]>0):
  print(f"yellow Circles")
  print(f"cx={yellow[:,0]}")
  print(f"cy={yellow[:,1]}")
  print(f"radii={yellow[:,2]}")


circle = cv2.imread("Original.jpg")

if(red.shape[0]>0):
  circle  = draw_circles(circle, red, green = 0)
if(green.shape[0]>0):
  circle  = draw_circles(circle, green, green = 1)
if(yellow.shape[0]>0):
  circle  = draw_circles(circle, yellow, green = -1)

circle = cv2.cvtColor(circle, cv2.COLOR_BGR2RGB)

fig = plt.figure(figsize=(10, 7))
plt.imshow(circle)
plt.axis('off')
plt.title("Circles") 

结果:

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71651920

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档