opencv - 对货架上的产品进行分割

标签 opencv image-processing

我正在尝试使用直方图投影来检测货架上产品的边缘。但我被困在 2 个级别。

我面临的挑战是:

  1. 如何从图像中获取最长的非货架部分,即从可用产品中检测货架上最宽产品的宽度。
  2. 如何使用自定义标记实现形态重建。消除

所有小的水平段,我正在生成 2 个标记,可以在“markers.png”(附件)中看到。有了它们,我正在计算两个标记的重建输出的最小值。

Need assistance on this.
Thanks a lot
Below is my python code for the same.
Below is my python code

********************************************************************************

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
import math

# Read the input image
img = cv.imread('C:\\Users\\672059\\Desktop\\p2.png')
# Converting from BGR to RGB. Default is BGR.
# img_rgb = cv.cvtColor(img, cv.COLOR_BGR2RGB)
# Resize the image to 150,150
img_resize = cv.resize(img, (150, 150))
# Get the dimensions of the image
img_h, img_w, img_c = img_resize.shape
# Split the image on channels
red = img[:, :, 0]
green = img[:, :, 1]
blue = img[:, :, 2]

# Defining a vse for erosion
vse = np.ones((img_h, img_w), dtype=np.uint8)

# Morphological Erosion for red channel
red_erode = cv.erode(red, vse, iterations=1)
grad_red = cv.subtract(red, red_erode)
# Morphological Erosion for green channel
green_erode = cv.erode(green, vse, iterations=1)
grad_green = cv.subtract(green, green_erode)
# Morphological Erosion for blue channel
blue_erode = cv.erode(blue, vse, iterations=1)
grad_blue = cv.subtract(blue, blue_erode)

# Stacking the individual channels into one processed image
grad = [grad_red, grad_green, grad_blue]
retrieved_img = np.stack(grad, axis=-1)
retrieved_img = retrieved_img.astype(np.uint8)
retrieved_img_gray = cv.cvtColor(retrieved_img, cv.COLOR_RGB2GRAY)
plt.title('Figure 1')
plt.imshow(cv.bitwise_not(retrieved_img_gray), cmap=plt.get_cmap('gray'))
plt.show()

# Hough Transform of the image to get the longest non shelf boundary from the image!
edges = cv.Canny(retrieved_img_gray, 127, 255)
minLineLength = img_w
maxLineGap = 10
lines = cv.HoughLinesP(edges, 1, np.pi/180, 127, minLineLength=1, maxLineGap=1)
temp = img.copy()
l = []
for x in range(0, len(lines)):
    for x1, y1, x2, y2 in lines[x]:
        cv.line(temp, (x1, y1), (x2, y2), (0, 255, 0), 2)
        d = math.sqrt((x2-x1)**2 + (y2-y1)**2)
        l.append(d)

# Defining a hse for erosion
hse = np.ones((1, 7), dtype=np.uint8)
opening = cv.morphologyEx(retrieved_img_gray, cv.MORPH_OPEN, hse)
plt.title('Figure 2')
plt.subplot(1, 2, 1), plt.imshow(img)
plt.subplot(1, 2, 2), plt.imshow(cv.bitwise_not(opening), 'gray')
plt.show()

# Dilation with disk shaped structuring element
horizontal_size = 7
horizontalstructure = cv.getStructuringElement(cv.MORPH_ELLIPSE, (horizontal_size, 1))
dilation = cv.dilate(opening, horizontalstructure)
plt.title('Figure 3')
plt.imshow(cv.bitwise_not(dilation), 'gray')
plt.show()
# Doing canny edge on dilated image
edge = cv.Canny(dilation, 127, 255)
plt.title('Figure 4')
plt.imshow(edges, cmap='gray')
plt.show()

h_projection = edge.sum(axis=1)
print(h_projection)
plt.title('Projection')
plt.plot(h_projection)
plt.show()


listing = []
for i in range(1, len(h_projection)-1):
    if h_projection[i-1] == 0 and h_projection[i] == 0:
        listing.append(dilation[i])
        listing.append(dilation[i-1])
        a = np.array([np.array(b) for b in l])
        h = len(l)
        _, contours, _ = cv.findContours(a, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
        x, y, w, h = cv.boundingRect(contours[0])
        y = y + i - h
        cv.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)
        l.clear()

plt.imshow(img)
plt.show()

# Generating a mask
black_bg = np.ones([img_h, img_w], dtype=np.uint8)
# Clone the black bgd image
left = black_bg.copy()
right = black_bg.copy()
# Taking 10% of the image width
ten = int(0.1 * img_w)
left[:, 0:ten+1] = 0
right[:, img_w-ten:img_w+1] = 0
plt.title('Figure 4')
plt.subplot(121), plt.imshow(left, 'gray')
plt.subplot(122), plt.imshow(right, 'gray')
plt.show()
# Marker = left and right. Mask = dilation
mask = dilation
marker_left = left
marker_right = right

********************************************************************************

markers.png 链接:/image/45WJ6.png

********************************************************************************

enter image description here

最佳答案

根据你输入的图像,我会:

  • 拍一张空冰箱的照片
  • 然后将当前图像与空图像进行比较。
  • 使用形态学操作
  • 获取连通分量 > 大小 N

如果您无法拍摄空冰箱图片:

  • 分割货架(阈值白色部分)
  • 利用货架的图像矩撤销图像的旋转
  • 对于每个货架:
    • 饱和度的阈值
    • 进行垂直投影
    • 计数最大值。

阈值:

enter image description here

腐 eclipse 扩张:

enter image description here

连接组件(宽度 > 10 * 高度 + > 最小尺寸): enter image description here

而且你有架子。

现在从每个架子取平均 Y 并将原始图像切割成几 block :

enter image description here

抖动到 8 种颜色:

enter image description here

和阈值:

enter image description here

Connected components (h>1.5*w, minsize...这很难,我玩过:)

enter image description here

关于opencv - 对货架上的产品进行分割,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51838940/

相关文章:

java - Douglas–Peucker 简化边

HTML5 Canvas 图像对比

android - OpenCV_2.4.2_binary_pack_armv7a源代码是否打开

c++ - 从 Iplimage 到 Mat 的转换不保留深度信息

c++ - OpenCV 类型独立图像访问的最佳方式?

c++ - Opencv Mat内存管理

python - 带有 Eclipse 的 OpenCV 2.3.1 Python 显示 synatx 错误但仍在运行

c - C 中最快的抖动/半色调库

python-2.7 - 在OpenCV 3.2.0中是cv2.cv.Round吗?

c++ - 如何将openCV导入到iOS 8项目中