Ely*_*ium 6 python opencv numpy hough-transform
我有这张林线作物的图像。我需要找到作物对齐的大致方向。我试图获取图像的霍夫线,然后找到角度分布的模式。
我一直在关注本关于裁剪线的教程,但是在该教程中,裁剪线很稀疏。这里它们是密集的,经过灰度、模糊和使用精明的边缘检测后,这就是我得到的
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('drive/MyDrive/tree/sample.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
gauss = cv2.GaussianBlur(gray, (3,3), 3)
plt.figure(figsize=(15,15))
plt.subplot(1,2,1)
plt.imshow(gauss)
gscale = cv2.Canny(gauss, 80, 140)
plt.subplot(1,2,2)
plt.imshow(gscale)
plt.show()
Run Code Online (Sandbox Code Playgroud)
(左侧未经canny处理的模糊图像,左侧经过canny预处理的图像)

之后,我按照教程将预处理后的图像“骨架化”
size = np.size(gscale)
skel = np.zeros(gscale.shape, np.uint8)
ret, gscale = cv2.threshold(gscale, 128, 255,0)
element = cv2.getStructuringElement(cv2.MORPH_CROSS, (3,3))
done = False
while not done:
eroded = cv2.erode(gscale, element)
temp = cv2.dilate(eroded, element)
temp = cv2.subtract(gscale, temp)
skel = cv2.bitwise_or(skel, temp)
gscale = eroded.copy()
zeros = size - cv2.countNonZero(gscale)
if zeros==size:
done = True
Run Code Online (Sandbox Code Playgroud)
给我
正如你所看到的,仍然有一堆曲线。当对其使用HoughLines算法时,有11k条线分散在各处
lines = cv2.HoughLinesP(skel,1,np.pi/180,130)
a,b,c = lines.shape
for i in range(a):
rho = lines[i][0][0]
theta = lines[i][0][1]
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, cv2.LINE_AA)#showing the results:
plt.figure(figsize=(15,15))
plt.subplot(121)#OpenCV reads images as BGR, this corrects so it is displayed as RGB
plt.plot()
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.title('Row Detection')
plt.xticks([])
plt.yticks([])
plt.subplot(122)
plt.plot()
plt.imshow(skel,cmap='gray')
plt.title('Skeletal Image')
plt.xticks([])
plt.yticks([])
plt.show()
Run Code Online (Sandbox Code Playgroud)
我是 cv2 的新手,所以我不知道该怎么做。搜索并尝试了很多东西但没有任何效果。如何去除稍大的点并去除波浪线?
您可以使用2D FFT来查找裁剪对齐的大致方向(如 mozway 在评论中提出的)。这个想法是,当输入包含同一方向的许多线时,可以轻松地从震级谱中出现的中心射束中提取总体方向。您可以在上一篇文章中找到有关其工作原理的更多信息。它直接处理输入图像,但最好应用高斯 + Canny 滤波器。
这是滤波后的灰度图像的幅度谱的有趣部分:
可以很容易地看到主光束。您可以通过迭代许多角度不断增加的线来提取其角度,并对每条线上的幅度值求和,如下图所示:
以下是根据线的角度(以弧度为单位)绘制的每条线的幅值总和:
在此基础上,您只需要找到使计算总和最大化的角度即可。
这是生成的代码:
def computeAngle(arr):
# Naive inefficient algorithm
n, m = arr.shape
yCenter, xCenter = (n-1, m//2-1)
lineLen = m//2-2
sMax = 0.0
bestAngle = np.nan
for angle in np.arange(0, math.pi, math.pi/300):
i = np.arange(lineLen)
y, x = (np.sin(angle) * i + 0.5).astype(np.int_), (np.cos(angle) * i + 0.5).astype(np.int_)
s = np.sum(arr[yCenter-y, xCenter+x])
if s > sMax:
bestAngle = angle
sMax = s
return bestAngle
# Load the image in gray
img = cv2.imread('lines.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
# Apply some filters
gauss = cv2.GaussianBlur(gray, (3,3), 3)
gscale = cv2.Canny(gauss, 80, 140)
# Compute the 2D FFT of real values
freqs = np.fft.rfft2(gscale)
# Shift the frequencies (centering) and select the low frequencies
upperPart = freqs[:freqs.shape[0]//4,:freqs.shape[1]//2]
lowerPart = freqs[-freqs.shape[0]//4:,:freqs.shape[1]//2]
filteredFreqs = np.vstack((lowerPart, upperPart))
# Compute the magnitude spectrum
magnitude = np.log(np.abs(filteredFreqs))
# Correct the angle
magnitude = np.rot90(magnitude).copy()
# Find the major angle
bestAngle = computeAngle(magnitude)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
158 次 |
| 最近记录: |