我正在尝试使用霍夫变换来检测图像中的线条。因此,我首先像这样创建累加器:
let parser = new DOMParser();
var data = "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<title>Database Error</title>\n<style type=\"text/css\">\n\n::selection{ background-color: #E13300; color: white; }\n::moz-selection{ background-color: #E13300; color: white; }\n::webkit-selection{ background-color: #E13300; color: white; }\n\nbody {\n\tbackground-color: #fff;\n\tmargin: 40px;\n\tfont: 13px/20px normal Helvetica, Arial, sans-serif;\n\tcolor: #4F5155;\n}\n\na {\n\tcolor: #003399;\n\tbackground-color: transparent;\n\tfont-weight: normal;\n}\n\nh1 {\n\tcolor: #444;\n\tbackground-color: transparent;\n\tborder-bottom: 1px solid #D0D0D0;\n\tfont-size: 19px;\n\tfont-weight: normal;\n\tmargin: 0 0 14px 0;\n\tpadding: 14px 15px 10px 15px;\n}\n\ncode {\n\tfont-family: Consolas, Monaco, Courier New, Courier, monospace;\n\tfont-size: 12px;\n\tbackground-color: #f9f9f9;\n\tborder: 1px solid #D0D0D0;\n\tcolor: #002166;\n\tdisplay: block;\n\tmargin: 14px 0 14px 0;\n\tpadding: 12px 10px 12px 10px;\n}\n\n#container {\n\tmargin: 10px;\n\tborder: 1px solid #D0D0D0;\n\t-webkit-box-shadow: 0 0 8px #D0D0D0;\n}\n\np {\n\tmargin: 12px 15px 12px 15px;\n}\n</style>\n</head>\n<body>\n\t<div id=\"container\">\n\t\t<h1>A Database Error Occurred</h1>\n\t\t<p>Error Number: 1062</p><p>Duplicate entry '60-2017' for key 'PRIMARY'</p><p>INSERT INTO `table` (`f1`, `f2`, `f3`, `f4`) VALUES ('60', '2017', '60_2017_Permohonan_d2030211.pdf', '2018-06-24 16:43:49')</p><p>Filename: /Applications/XAMPP/xamppfiles/htdocs/fol/models/rek/m_rek.php</p><p>Line Number: 47</p>\t</div>\n</body>\n</html>";
let doc = parser.parseFromString(data, "text/html");
console.log(doc.querySelector("#container p").innerHTML);
然后像这样调用函数:
from math import hypot, pi, cos, sin
from PIL import Image
import numpy as np
import cv2 as cv
import math
def hough(img):
thetaAxisSize = 460 #Width of the hough space image
rAxisSize = 360 #Height of the hough space image
rAxisSize= int(rAxisSize/2)*2 #we make sure that this number is even
img = im.load()
w, h = im.size
houghed_img = Image.new("L", (thetaAxisSize, rAxisSize), 0) #legt Bildgroesse fest
pixel_houghed_img = houghed_img.load()
max_radius = hypot(w, h)
d_theta = pi / thetaAxisSize
d_rho = max_radius / (rAxisSize/2)
#Accumulator
for x in range(0, w):
for y in range(0, h):
treshold = 255
col = img[x, y]
if col >= treshold: #determines for each pixel at (x,y) if there is enough evidence of a straight line at that pixel.
for vx in range(0, thetaAxisSize):
theta = d_theta * vx #angle between the x axis and the line connecting the origin with that closest point.
rho = x*cos(theta) + y*sin(theta) #distance from the origin to the closest point on the straight line
vy = rAxisSize/2 + int(rho/d_rho+0.5) #Berechne Y-Werte im hough space image
pixel_houghed_img[vx, vy] += 1 #voting
return houghed_imgcode here
结果似乎还可以:
所以问题来了。我知道要在hough空间中找到前3个最高值并将其转换回3行。最高值应该是最强的线。
因此,我首先在像素阵列中寻找最大值,并取我发现的最大值的X和Y值。从我的理解来看,X和Y值就是我的rho和theta。我发现这样的最大值:
im = Image.open("img3.pgm").convert("L")
houghed_img = hough(im)
houghed_img.save("ho.bmp")
houghed_img.show()
现在我要使用此rho和theta值绘制检测到的线条。我使用以下代码进行此操作:
def find_maxima(houghed_img):
w, h = houghed_img.size
max_radius = hypot(w, h)
pixel_houghed_img = houghed_img.load()
max1, max2, max3 = 0, 0, 0
x1position, x2position, x3position = 0, 0, 0
y1position, y2position, y3position = 0, 0, 0
rho1, rho2, rho3 = 0, 0, 0
theta1, theta2, theta3 = 0, 0, 0
for x in range(1, w):
for y in range(1, h):
value = pixel_houghed_img[x, y]
if(value > max1):
max1 = value
x1position = x
y1position = y
rho1 = x
theta1 = y
elif(value > max2):
max2 = value
x2position = x
x3position = y
rho2 = x
theta2 = y
elif(value > max3):
max3 = value
x3position = x
y3position = y
rho3 = x
theta3 = y
print('max', max1, max2, max3)
print('rho', rho1, rho2, rho3)
print('theta', theta1, theta2, theta3)
# Results of the print:
# ('max', 255, 255, 255)
# ('rho', 1, 1, 1)
# ('theta', 183, 184, 186)
return rho1, theta1, rho2, theta2, rho3, theta3
但是,结果似乎是错误的:
所以我的假设是,当我在find_maxima()函数中声明rho和theta值时,我做错了什么,这意味着这有问题:
img_copy = np.ones(im.size)
rho1, theta1, rho2, theta2, rho3, theta3 = find_maxima(houghed_img)
a1 = math.cos(theta1)
b1 = math.sin(theta1)
x01 = a1 * rho1
y01 = b1 * rho1
pt11 = (int(x01 + 1000*(-b1)), int(y01 + 1000*(a1)))
pt21 = (int(x01 - 1000*(-b1)), int(y01 - 1000*(a1)))
cv.line(img_copy, pt11, pt21, (0,0,255), 3, cv.LINE_AA)
a2 = math.cos(theta2)
b2 = math.sin(theta2)
x02 = a2 * rho2
y02 = b2 * rho2
pt12 = (int(x02 + 1000*(-b2)), int(y02 + 1000*(a2)))
pt22 = (int(x02 - 1000*(-b2)), int(y02 - 1000*(a2)))
cv.line(img_copy, pt12, pt22, (0,0,255), 3, cv.LINE_AA)
a3 = math.cos(theta3)
b3 = math.sin(theta3)
x03 = a3 * rho3
y03 = b3 * rho3
pt13 = (int(x03 + 1000*(-b3)), int(y03 + 1000*(a3)))
pt23 = (int(x03 - 1000*(-b3)), int(y03 - 1000*(a3)))
cv.line(img_copy, pt13, pt23, (0,0,255), 3, cv.LINE_AA)
cv.imshow('lines', img_copy)
cv.waitKey(0)
cv.destroyAllWindows()
或者我在将rho和theta值转换回一行时做错了。
如果有人可以帮助我,我将非常感激!
Edit1:根据要求,请找到原始图像,我想从下面找到这些行:
Edit2: 感谢@Alessandro Jacopson和@Cris Luegno的投入,我得以做出一些改变,这些改变肯定给了我一些希望!
在我的def hough(img)中:我将阈值设置为255,这意味着我只投票给白色像素,这是错误的,因为我想查看黑色像素,因为这些像素将指示线条而不是黑色我图像的白色背景。因此,在def hough(img):中累加器的计算现在看起来像这样:
max1 = value
x1position = x
y1position = y
rho1 = x
theta1 = y
使用find_maxima()函数时,这将导致以下累加器以及以下rho和thea值:
#Accumulator
for x in range(0, w):
for y in range(0, h):
treshold = 0
col = img[x, y]
if col <= treshold: #determines for each pixel at (x,y) if there is enough evidence of a straight line at that pixel.
for vx in range(0, thetaAxisSize):
theta = d_theta * vx #angle between the x axis and the line connecting the origin with that closest point.
rho = x*cos(theta) + y*sin(theta) #distance from the origin to the closest point on the straight line
vy = rAxisSize/2 + int(rho/d_rho+0.5) #Berechne Y-Werte im hough space image
pixel_houghed_img[vx, vy] += 1 #voting
return houghed_img
我可以从这些值绘制的线条如下所示:
因此,此结果要好得多,但似乎仍然存在问题。我强烈怀疑这里还是有问题:
# Results of the prints: (now top 8 instead of top 3)
# ('max', 155, 144, 142, 119, 119, 104, 103, 98)
# ('rho', 120, 264, 157, 121, 119, 198, 197, 197)
# ('theta', 416, 31, 458, 414, 417, 288, 291, 292)
在这里,我将rho和theta分别设置为[0 ... w] [0 ... h]。我认为这是错误的,因为在Hough空间中X的值以及为什么Y不为0、1、2、3 ...,因为我们在另一个空间中。因此,我假设我必须将X和Y乘以某些值,以使它们返回到Hough空间。但这只是一个假设,也许你们还能想到其他事情吗?
再次非常感谢亚历山德罗(Alessandro)和克里斯(Cris)在这里帮助我!
Edit3:工作代码,感谢@Cris Luengo
for x in range(1, w):
for y in range(1, h):
value = pixel_houghed_img[x, y]
if(value > max1):
max1 = value
x1position = x
y1position = y
rho1 = value
theta1 = x
原始图片:
累加器:
成功的线路检测:
答案 0 :(得分:2)
首先,在How to create a Minimal, Complete, and Verifiable example之后,如果可能,您应该发布图片img3.pgm
或为其提供链接。
然后,您写道:
# Results of the print:
# ('max', 255, 255, 255)
# ('rho', 1, 1, 1)
# ('theta', 183, 184, 186)
因此rho
在三行中是相同的,并且theta
在183和186之间变化不大;因此,三条线几乎彼此相等,并且这一事实与您用来获得线方程并绘制它的方法无关。
根据教程Hough Line Transform,在您看来,您在直线上找到两个点的方法是正确的。这就是本教程的建议,在我看来,这等同于您的代码:
lines = cv2.HoughLines(edges,1,np.pi/180,200)
for rho,theta in lines[0]:
a = np.cos(theta)
b = np.sin(theta)
x0 = a*rho
y0 = b*rho
x1 = int(x0 + 1000*(-b))
y1 = int(y0 + 1000*(a))
x2 = int(x0 - 1000*(-b))
y2 = int(y0 - 1000*(a))
cv2.line(img,(x1,y1),(x2,y2),(0,0,255),2)
我怀疑峰值发现算法可能不正确。 您的峰发现算法会先找到最大峰的位置,然后再找到两个非常接近最大峰的位置。
为简单起见,只看一维会发生什么,期望使用峰值发现算法在x=-1
,x=0
和x=1
处找到三个峰值位置,并且峰值应接近.25,.5和1。
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-2, 2, 1000)
y = np.exp(-(x-1)**2/0.01)+.5*np.exp(-(x)**2/0.01)+.25*np.exp(-(x+1)**2/0.01)
max1, max2, max3 = 0, 0, 0
m1 = np.zeros(1000)
m2 = np.zeros(1000)
m3 = np.zeros(1000)
x1position, x2position, x3position = 0, 0, 0
for i in range(0,1000):
value = y[i]
if(value > max1):
max1 = value
x1position = x[i]
elif(value > max2):
max2 = value
x2position = x[i]
elif(value > max3):
max3 = value
x3position = x[i]
m1[i] = max1
m2[i] = max2
m3[i] = max3
print('xposition',x1position, x2position, x3position )
print('max', max1, max2, max3)
plt.figure()
plt.subplot(4,1,1)
plt.plot(x, y)
plt.ylabel('$y$')
plt.subplot(4,1,2)
plt.plot(x, m1)
plt.ylabel('$max_1$')
plt.subplot(4,1,3)
plt.plot(x, m2)
plt.ylabel('$max_2$')
plt.subplot(4,1,4)
plt.plot(x, m3)
plt.xlabel('$x$')
plt.ylabel('$max_3$')
plt.show()
输出为
('xposition', 0.99899899899899891, 1.0030030030030028, 1.0070070070070072)
('max', 0.99989980471948192, 0.99909860379824966, 0.99510221871862647)
这不是预期的结果。
要检测2D场中的多个峰,您应该查看一下此Peak detection in a 2D array
答案 1 :(得分:2)
这部分代码似乎不正确:
library(dplyr) library(tidyr) df %>% spread(dist, cumRate) %>% mutate(higher_dist = case_when( `100` > npr ~ '100', npr > `100` ~ 'npr', TRUE ~ 'equal') ) %>% filter(npr != `100`) %>% group_by(loc) %>% arrange(year) %>% slice(1) loc year `100` npr higher_dist <fct> <dbl> <dbl> <dbl> <chr> 1 a 2 1 0 100 2 b 1 3 0 100
如果max1 = value
x1position = x
y1position = y
rho1 = value
theta1 = x
和x
是参数空间中的两个坐标,则它们将对应于y
和rho
。将theta
设置为等于该值没有意义。我也不知道为什么存储rho
和x1position
,因为您不使用这些变量。
接下来,您需要将这些坐标转换回实际的rho和theta值,并反转在编写时所做的转换:
y1position
倒数是:
theta = d_theta * vx #angle between the x axis and the line connecting the origin with that closest point.
rho = x*cos(theta) + y*sin(theta) #distance from the origin to the closest point on the straight line
vy = rAxisSize/2 + int(rho/d_rho+0.5) #Berechne Y-Werte im hough space image