检测白色像素密度低的区域

Posted

技术标签:

【中文标题】检测白色像素密度低的区域【英文标题】:Detect areas with low density of white pixels 【发布时间】:2019-02-14 18:03:58 【问题描述】:

我是一名学生,试图分析几乎整张图片都是黑色的二进制图像,但图像中均匀分布着一些白色像素。我想检测整个图像是否具有均匀的白色像素密度。如果图像中的区域具有低密度的白色像素,我想检测它。

在下图中,我标记了一个没有白色像素的区域作为我想要检测的示例:

在我的程序中,我在制作图片之前获取了白色像素的坐标。然后我创建一个黑色 BufferedImage 并在每个坐标上写入一个白色像素以创建我附加的图像。 对我来说,最重要的是检测图像是否包含大于可调整大小的完全黑色区域(我必须尝试找到正确的设置)

如果可以简单地通过使用白色像素的坐标(无需创建黑色图像然后添加所有白色像素)以一种好的方式检测到这一点,那么我也会感兴趣。

我在我的程序中使用 Java 和 OpenCV,有人对如何继续执行此操作有任何建议吗? OpenCV 中有什么功能可以帮助我吗?

感谢所有答案

【问题讨论】:

你可以用不同大小的白色圆圈对图像进行卷积。卷积后,图像中最暗的像素将是缝隙的位置 如果有人没有回答,我今晚可能有时间整理一个小演示。 谢谢,非常感谢您的回复 您要查找的区域在距离变换的最大值附近 【参考方案1】:

这是解决此问题的一种粗略方法。我使用 python 解决了这个问题,但所有相同的规则都适用于 Java。

我首先获得一组测试点来使用它,它有一个差距和一些随机性。

w, h = 1000, 1000
spacing = 25
blast_size = 100


def distance(p1, p2):
    return math.sqrt(math.pow(p1[0] - p2[0], 2) + math.pow(p1[1] - p2[1], 2))


def keep_point(p):
    if p[0] < 0 or p[0] >= w or p[1] < 0 or p[1] >= h:
        return False
    d = distance(p, (w/2, h/2))
    if d > blast_size:
        return True
    return False


grid = [
    (i + random.randint(-spacing, spacing), j + random.randint(-spacing, spacing))
    for i in range(spacing, w, spacing*2)
    for j in range(spacing, h, spacing*2)
]
grid = list(filter(keep_point, grid))


initial = np.zeros((h, w), np.uint8)
for i, j in grid:
    image[i, j] = 255

cv2.imshow("Initial", initial)
cv2.waitKey()

接下来我计算每个点到邻居的最小距离。最大的最小距离将用作我们卷积的半径。卷积完成后,差距会非常明显。为了得到卷积后间隙的中心,我取轮廓的平均值。如果可以有多个间隙,则此时需要进行斑点检测。

# Don't include self as a neighbor
def distance_non_equal(p1, p2):
    if p1 == p2:
        return float('inf')
    return distance(p1, p2)


min_distance = [
    min(map(lambda p2: distance_non_equal(p1, p2), grid))
    for p1 in grid
]

radius = int(max(min_distance))

kernel = np.zeros((2*radius+1, 2*radius+1), np.uint8)
y,x = np.ogrid[-radius:radius+1, -radius:radius+1]
mask = x**2 + y**2 <= radius**2
kernel[mask] = 255

convolution = cv2.filter2D(image, cv2.CV_8U, kernel)

contours = cv2.findContours(convolution, 0, 2)
avg = np.mean(contours[0],axis=1)
x = int(round(avg[0,0,0]))
y = int(round(avg[0,0,1]))

convolution[x, y] = 255
cv2.imshow("Convolution", convolution)
cv2.waitKey()

现在我们有了间隙的中心,我们可以近似边界。这是用于检测边界的非常粗略的算法。我根据它们与中心点的角度将点划分为区域。对于每个区域,我将最近的点算作边界的一部分。最后,我给边框点上色。

def get_angle(p):
    angle = math.degrees(math.atan2(y - p[1], x - p[0]))
    if angle < 0:
        angle += 360
    return angle

angles = list(map(get_angle, grid))
zones = [
    [
        p
        for angle, p in zip(angles, grid)
        if i < angle < i + 360//12
    ]
    for i in range(0,360,360//12)
]

closest = [
    min(zone, key=lambda p2: distance((x,y), p2))
    for zone in zones
]

final = np.zeros((h, w, 3), np.uint8)
for i, j in grid:
    final[i, j] = [100,100,100]
for i, j in closest:
    final[i, j] = [255,255,255]

cv2.imshow("final", final)
cv2.waitKey()

【讨论】:

非常感谢您的回答!不幸的是,我对phyton了解不多,但我通过使用距离变换达到了我的目标。

以上是关于检测白色像素密度低的区域的主要内容,如果未能解决你的问题,请参考以下文章

Android中的网络应用之网页设置,检测、配置用户设备属性。

PHP - 检测图像周围空白的真正快速方法?

检测图像像素的列或行是不是为线

opencv如何读取多边形区域内的像素值?

Opencv c ++检测并裁剪图像上的白色区域

jQuery - 检测特定像素区域的点击,然后执行功能