从背景(墙壁)检测前景(岩石/库存)以找到材料角度

Tan*_*han 5 python opencv image-processing image-segmentation

我试图通过使用大津阈值分割图像来找到库存的角度(左侧和右侧)。我的图像是这样的:

原始照片

在代码中,我对其进行分段并找到图像中的第一个黑色像素

分割照片

分割的照片在白色背景中似乎没有任何黑色像素,但即使我使用了morphology.opening

在此输入图像描述

如果我将它与不同的图像一起使用,似乎没有这个问题

在此输入图像描述

我该如何解决这个问题?有任何想法吗?(下一步是找到左侧和右侧的角度)

代码附在这里


from skimage import io, filters, morphology, measure
import numpy as np
import cv2 as cv
from scipy import ndimage
import math
# Load the image
image = io.imread('mountain3.jpg', as_gray=True)

# Apply Otsu's thresholding to segment the image
segmented_image = image > filters.threshold_otsu(image)

# Perform morphological closing to fill small gaps
structuring_element = morphology.square(1)
closed_image = morphology.closing(segmented_image, structuring_element)

# Apply morphological opening to remove small black regions in the white background
structuring_element = morphology.disk(10)  # Adjust the disk size as needed
opened_image = morphology.opening(closed_image, structuring_element)

# Fill larger gaps using binary_fill_holes
#filled_image = measure.label(opened_image)
#filled_image = filled_image > 0

# Display the segmented image after filling the gaps
io.imshow(opened_image)

io.show()
# Find the first row containing black pixels
first_black_row = None
for row in range(opened_image.shape[0]):
    if np.any(opened_image[row, :] == False):
        first_black_row = row
        break

if first_black_row is not None:
    edge_points = []  # List to store the edge points

    # Iterate over the rows below the first black row
    for row in range(first_black_row, opened_image.shape[0]):
        black_pixel_indices = np.where(opened_image[row, :] == False)[0]

        if len(black_pixel_indices) > 0:
            # Store the first black pixel coordinates on the left and right sides
            left_x = black_pixel_indices[0]
            right_x = black_pixel_indices[-1]
            y = row

            # Append the edge point coordinates
            edge_points.append((left_x, y))
            edge_points.append((right_x, y))

    if len(edge_points) > 0:
        # Plotting the edge points
        import matplotlib.pyplot as plt

        edge_points = np.array(edge_points)

        plt.figure()
        plt.imshow(opened_image, cmap='gray')
        plt.scatter(edge_points[:, 0], edge_points[:, 1], color='red', s=1)
        plt.title('Edge Points')
        plt.show()
    else:
        print("No edge points found.")
else:
    print("No black pixels found in the image.")
Run Code Online (Sandbox Code Playgroud)

Chr*_*itz 4

您的问题是图像有噪点。你需要处理噪音。

这通常是通过某种低通,即模糊来完成的。我建议使用中值模糊。

这是中值滤波器的结果,内核大小为 9:

中位数,内核大小 9

以及与源的每像素绝对差异,幅度放大 20 倍:

在此输入图像描述

(这表明您可以进行带通来捕捉堆的“纹理”与背景的平坦度)

这是 Otsu 阈值处理(和反演)后的图片:

大津

而且你的前景与背景几乎没有对比。如果您有更好的对比背景,这几乎不会成为一个问题。

这是基于色调的阈值处理,因为背景和前景的色调略有不同:

大津温色相

形态学闭运算:

形态闭合


为了获得库存的左坡和右坡的线条,您无论如何都需要处理轮廓或边缘像素的东西。

轮廓查找和连接组件标记都会遇到问题,这就是为什么推荐这些的答案也必须建议明确过滤结果以去除小碎片(噪音)。

因此,这些方法(轮廓/CC)并不能解决噪声问题,它们只是将其转化为另一个问题,在处理图像之后,您仍然必须处理噪声(通过过滤它) 。

我建议尽早处理噪音。