知道这些线条的角度后,在质量很差的图像上找到线条的最佳方法是什么?
What's the best way to find lines on a very poor quality image, knowing the angle of these lines?
我正在尝试使用 Houghlines 变换找到这两条水平线。如您所见,图片非常嘈杂!目前我的工作流程是这样的:
裁剪图像
模糊一下
降低噪点(为此,我反转图像,然后将模糊图像减去反转图像)
打开它并用“水平内核”扩展它(kernel_1 = np.ones((10,1), np.uint8)
阈值
豪格线
结果不如预期...有没有更好的策略,知道我会一直搜索水平线(因此,abs (theta) 将始终接近于 0 或 pi)
问题是噪音和微弱的信号。你可以用 averaging/integration 抑制噪音,同时保持信号,因为它是沿着一个维度复制的(信号是一条线)。
您使用非常宽但窄的内核的方法可以扩展为简单地沿整个图像进行积分。
- 旋转图像,使可疑线与轴对齐(假设水平)
- 对一条扫描线(水平线)的所有像素求和,
np.sum(axis=1)
或均值,无论哪种方式都要注意数据类型。使用浮点数很方便。
- 使用一维值序列。
这不会告诉您这条线有多长,只会告诉您它在那里并且可能跨越整个宽度。
编辑:既然我的回答有反应,我也会详细说明:
我认为你可以低通它以获得“灰色”基线,然后减去(“高斯差异”)。那应该会给你一个很好的信号。
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
import scipy.ndimage
im = cv.imread("0gczo.png", cv.IMREAD_GRAYSCALE) / np.float32(255)
relief = im.mean(axis=1)
smoothed = scipy.ndimage.gaussian_filter(relief, sigma=2.0)
baseline = scipy.ndimage.gaussian_filter(relief, sigma=10.0)
difference = smoothed - baseline
std = np.std(difference)
level = 2
outliers = (difference <= std * -level)
plt.plot(difference)
plt.hlines([std * +level, std * -level], xmin=0, xmax=len(relief))
plt.plot(std * -level + outliers * std)
plt.show()
# where those peaks are:
edgemap = np.diff(outliers.astype(np.int8))
(edges,) = edgemap.nonzero()
print(edges) # [392 398 421 427]
print(edgemap[edges]) # [ 1 -1 1 -1]
与 Christoph 的回答大致相同,但只是想分享一张我无法在评论中分享的处理过的图像。
我只是对 np.mean(axis=1)
的行取平均值并对结果进行归一化。希望您能看到与您的线条对应的两条暗带。
我正在尝试使用 Houghlines 变换找到这两条水平线。如您所见,图片非常嘈杂!目前我的工作流程是这样的:
裁剪图像
模糊一下
降低噪点(为此,我反转图像,然后将模糊图像减去反转图像)
打开它并用“水平内核”扩展它(
kernel_1 = np.ones((10,1), np.uint8)
阈值
豪格线
结果不如预期...有没有更好的策略,知道我会一直搜索水平线(因此,abs (theta) 将始终接近于 0 或 pi)
问题是噪音和微弱的信号。你可以用 averaging/integration 抑制噪音,同时保持信号,因为它是沿着一个维度复制的(信号是一条线)。
您使用非常宽但窄的内核的方法可以扩展为简单地沿整个图像进行积分。
- 旋转图像,使可疑线与轴对齐(假设水平)
- 对一条扫描线(水平线)的所有像素求和,
np.sum(axis=1)
或均值,无论哪种方式都要注意数据类型。使用浮点数很方便。 - 使用一维值序列。
这不会告诉您这条线有多长,只会告诉您它在那里并且可能跨越整个宽度。
编辑:既然我的回答有反应,我也会详细说明:
我认为你可以低通它以获得“灰色”基线,然后减去(“高斯差异”)。那应该会给你一个很好的信号。
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
import scipy.ndimage
im = cv.imread("0gczo.png", cv.IMREAD_GRAYSCALE) / np.float32(255)
relief = im.mean(axis=1)
smoothed = scipy.ndimage.gaussian_filter(relief, sigma=2.0)
baseline = scipy.ndimage.gaussian_filter(relief, sigma=10.0)
difference = smoothed - baseline
std = np.std(difference)
level = 2
outliers = (difference <= std * -level)
plt.plot(difference)
plt.hlines([std * +level, std * -level], xmin=0, xmax=len(relief))
plt.plot(std * -level + outliers * std)
plt.show()
# where those peaks are:
edgemap = np.diff(outliers.astype(np.int8))
(edges,) = edgemap.nonzero()
print(edges) # [392 398 421 427]
print(edgemap[edges]) # [ 1 -1 1 -1]
与 Christoph 的回答大致相同,但只是想分享一张我无法在评论中分享的处理过的图像。
我只是对 np.mean(axis=1)
的行取平均值并对结果进行归一化。希望您能看到与您的线条对应的两条暗带。