霍夫变换用于使用python进行正弦波检测

时间:2019-02-27 17:16:53

标签: python numpy

我正在尝试使用python改编Hough变换;在这种情况下,我需要寻找一个霍夫变换来检测正弦波。物镜曲线的形状为:y = amp * sin(ω+ɸ)+ y0。其中:amp =幅度,ω=频率(常数= 1(一个周期)),(ɸ)theta =相位,y0 =偏移量。

目标图片的长度为360像素,高度为300像素(附加示例) 目的是生成最佳[amp,theta,y0]的np阵列作为输出,然后将其绘制在原始图像上。 任何帮助都非常感谢 enter image description here

我不知道到目前为止我的代码出了什么问题,但是结果很糟糕。 这些是我的逐步代码:

# Import libraries to work
import cv2
import numpy as np
from matplotlib import pyplot as plt

# Reading image & canny  for edges
img = cv2.imread('s3.png',0) # "0" For gray scale
edges = cv2.Canny(img, threshold1 = 0, threshold2 = 50, apertureSize = 3)

# Hough Transform for sine detection
# y(x) = amp*sin(wx + theta) + y0  # Target equation
# amp = (y - y0)/sin(wx + theta)     # Search equation

# following code is an adaption from:
# http://nabinsharma.wordpress.com/2012/12/26/linear-hough-transform-using-python/
#https://gist.github.com/ilyakava/c2ef8aed4ad510ee3987/6b69a16dba2d97eaa585f35c025dac57ffb58651 
def hough_transform(img_bin, theta_res=1, amp_res=1, y0_res=1):
  nR,nC = img_bin.shape
  theta = np.linspace(0, 360, np.ceil(360/theta_res) + (1.0))
  y0 = np.linspace(0, 300, np.ceil(300/y0_res) + (1.0))
  amp = np.linspace(0, 300, np.ceil(300/amp_res) + (1.0))
  H = np.zeros((len(amp), len(theta), len(y0)))
  for rowIdx in range(nR):
    for colIdx in range(nC):
      if img_bin[rowIdx, colIdx]:
        for thIdx in range(len(theta)):
            for y0Idx in range(len(y0)):
                ampVal = (rowIdx - y0[y0Idx]) / np.sin((colIdx + theta[thIdx]))#*np.pi/180)
                ampIdx = np.nonzero(np.abs(amp-ampVal) == np.min(np.abs(amp-ampVal))) 
                H[ampIdx, thIdx, y0Idx] += 1      
  return amp, theta, y0, H
amps, thetas, y0s, H = hough_transform(edges)

# Best Amps, Thetas and y0s Selection – From:
#https://gist.github.com/ilyakava/c2ef8aed4ad510ee3987/6b69a16dba2d97eaa585f35c025dac57ffb58651
def top_n_amp_theta_y0(ht_acc_matrix, n, amps, thetas, y0s):
  '''
  @param hough transform accumulator matrix H (amp by theta by y0s)
  @param n of amps, thetas ans y0s desired
  @param ordered array of amps represented by rows in H
  @param ordered array of thetas represented by columns in H
  @param ordered array of y0s represented by deep in H
  @return top n amp, theta and y0 in H by accumulator value
  @return x,y,z indexes in H of top n amp, theta and y0
  '''
  flat1 = np.hstack(ht_acc_matrix) 
  flat2 = np.hstack(flat1)
  flat = list(set(flat2))
  flat_sorted = sorted(flat, key = lambda n: -n)
  coords_sorted = [(np.argwhere(ht_acc_matrix == acc_value)) for acc_value in flat_sorted[0:n]]
  amp_theta_y0 = []
  x_y_z = []
  for coords_for_val_idx in range(0, len(coords_sorted), 1):
    coords_for_val = coords_sorted[coords_for_val_idx]
    for i in range(0, len(coords_for_val), 1):
      n,m,l = coords_for_val[i] # n by m by l matrix
      amp = amps[n]
      theta = thetas[m]
      y0 = y0s[l]
      amp_theta_y0.append([amp, theta, y0])
      x_y_z.append([m, n, l]) # just to unnest and reorder coords_sorted
  return [amp_theta_y0[0:n], x_y_z]
amp_theta_y0, x_y_z = top_n_amp_theta_y0(H, 1000, amps, thetas, y0s)

# From [amp_theta_y0] plot the best values on the original image
x = np.linspace(0, 360, 360)
y = amp1*np.sin((x + theta1*np.pi/180) ) + (y0_1)
q = amp2*np.sin((x + theta2*np.pi/180) ) + (y0_2)
x1, x2 = (0, 360)
y1, y2 = (300, 0)
fig, ax = plt.subplots()
ax.imshow(edges, extent=[x1, x2, y1, y2], aspect='auto', cmap='gray')
ax.plot(x, y, q)
plt.show()

0 个答案:

没有答案