当前位置: 首页 > 知识库问答 >
问题:

需要使用opencv识别“托盘是空的还是不空的”

拓拔泓
2023-03-14

我想在python中使用OpenCV识别给定图像中的托盘是否为空。

以下是我尝试过的

  1. 使用下面的代码检测最大的矩形并裁剪
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
thresh = cv2.erode(thresh, kernel, iterations=4)
thresh = cv2.dilate(thresh, kernel, iterations=4)
cnts, hier = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# Find the biggest contour
max_area = -1
max_c = 0
for i in range(len(cnts)):
    contour = cnts[i]
    area = cv2.contourArea(contour)
    if (area > max_area):
        max_area = area
        max_c = i
contour = cnts[max_c]

areas = [cv2.contourArea(c) for c in cnts]
max_index = np.argmax(areas)
cnt=cnts[max_index]

x,y,w,h = cv2.boundingRect(cnt)

crop_img = img[y:y+h, x:x+w]
#Create empty mask and flood fill
mask = np.zeros(edges.shape)
#Create 3-channel alpha mask
mask_stack = np.dstack([mask]*3)

它适用于中型和大型物体,但当我放硬币等小型物体时,这种方法不起作用,因为托盘也有一些划痕和灰尘。这是我在python中使用OpenCV的第一个项目

请帮助找到满足此要求的解决方案

共有1个答案

松烨烨
2023-03-14

我建议您:

    < li >进行相机校准,使图像中的线条变直,以及 < li >将您的相机与生产线对齐,这样您可以简化图像处理并使其更加稳定,以及 < li >尽可能使用更好的照明条件。

鉴于上面的图片,这里有一个蛮力解决方案:

  • 您可以首先通过HSV分割提取感兴趣区域(ROI),然后进行轮廓检测,然后使用此SO答案提取托盘的矩形形状
#!/usr/bin/python3
# -*- coding: utf-8 -*-

import cv2
import numpy as np

# Ref: https://stackoverflow.com/questions/37177811
def crop_minAreaRect(img, rect):

    box = cv2.boxPoints(rect) 
    box = np.int0(box)

    W = rect[1][0]
    H = rect[1][1]

    Xs = [i[0] for i in box]
    Ys = [i[1] for i in box]
    x1 = min(Xs)
    x2 = max(Xs)
    y1 = min(Ys)
    y2 = max(Ys)

    angle = rect[2]
    
    rotated = False

    if angle < -45:
        angle += 90
        rotated = True
    # Center of rectangle in source image
    center = ((x1+x2)/2,(y1+y2)/2)
    # Size of the upright rectangle bounding the rotated rectangle
    size = (x2-x1, y2-y1)
    M = cv2.getRotationMatrix2D((size[0]/2, size[1]/2), angle, 1.0)
    # Cropped upright rectangle
    cropped = cv2.getRectSubPix(img, size, center)
    cropped = cv2.warpAffine(cropped, M, size)
    croppedW = W if not rotated else H 
    croppedH = H if not rotated else W
    # Final cropped & rotated rectangle
    croppedRotated = cv2.getRectSubPix(cropped, (int(croppedW),int(croppedH)), (size[0]/2, size[1]/2))
    return croppedRotated

def ROI(img):
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

    lower_hsv = np.array([0, 0, 135]) # 0, 0, 135
    higher_hsv = np.array([180, 20, 240]) # 180, 20, 240

    mask = cv2.inRange(hsv, lower_hsv, higher_hsv)

    seg = cv2.bitwise_and(img, img, mask=mask)

    seg_gray = cv2.cvtColor(seg, cv2.COLOR_BGR2GRAY)

    k1 = 51
    seg_gauss = cv2.GaussianBlur(seg_gray, (k1, k1), 0)
    seg_th = cv2.threshold(seg_gauss, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]

    contours, hierarchy = cv2.findContours(image=seg_th, mode=cv2.RETR_EXTERNAL, method=cv2.CHAIN_APPROX_NONE)
    for i, cnt in enumerate(contours):
        if  cv2.contourArea(cnt)>1000000:
            x,y,w,h = cv2.boundingRect(cnt)     
            rect = cv2.minAreaRect(cnt)

    roi = crop_minAreaRect(img, rect)
    return roi
  • 当您将问题简化为特定的ROI时,您可以使用边缘检测、形态学和过滤,如下所示:
def ImProc(roi):

    gray = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)

    k_smooth = 5
    gauss = cv2.GaussianBlur(gray, (k_smooth, k_smooth), 0)

    # # Canny
    edges = cv2.Canny(gauss,0,255)

    k = 31 #300
    kernel = np.ones((k,k),np.uint8)
    mph = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)

    res = cv2.medianBlur(mph, 21)

    return res

我将这种方法应用于给定的图像:

empty = cv2.imread("empty.jpg")
full = cv2.imread("full.jpg")

roi_empty = ROI(empty)
roi_full = ROI(full)

res_empty = ImProc(roi_empty)
res_full = ImProc(roi_full)

cv2.namedWindow("res_full", cv2.WINDOW_NORMAL)
cv2.imshow("res_full", res_full)

cv2.waitKey(0)

对于满托盘(旋转),我得到了以下结果:

请注意,此解决方案受不同参数的影响,为了更好地控制它们并获得稳定的结果,我建议您考虑上面的建议。

 类似资料:
  • 问题内容: 我正在使用postgreSQL。我有一列: 但是,当我想插入带有空字符串的行时,如下所示: 它不会给我错误并接受。如何检查插入值应为?(既不为空也不为空) PS: 我的专栏定义为: 问题答案: 向列定义添加约束。例如类似: 有关更多信息,请参见http://www.postgresql.org/docs/current/static/ddl- constraints.html

  • 我想运行一个复杂的HQL查询。我的一个参数是< code >集合 类似: spring甚至不能启动< code >???未映射 从表t中选择t,其中size((:codes)) = 0或t.code IN (:codes) 和许多其他人 是否有一种通用方法可以进行此检查并使此查询在不完全构建查询的情况下工作?

  • 问题内容: 考虑以下代码块: 当我在构造函数中初始化两个变量(和)时,其他两个变量(和)是否需要内存中的空间来存储null值? Q1。如果它们确实需要空间,那么值将占用多少内存?(例如,占用4个字节)。 Q2。字符串在内存中占用多少空间?字符串需要多少存储空间?它取决于字符串的长度吗? 问题答案: 在Java中,它只是引用(基本上是受限制的指针)可以具有的值。这意味着引用没有任何意义。在这种情况下

  • 随着新的工具栏小部件的引入和AppCompat(android.support.v7.widget.Toolbar)版本的推出,是否还需要调用setSupportActionbar(工具栏)?或者调用setSupportActionbar有什么好处吗;现在我们可以设置标题、子标题、导航图标、导航图标单击侦听器(getSupportActionBar()。直接在工具栏上设置DisplayHomeAs

  • 主要的问题是如何检测雄辩的收集结果是否为空,laravel建议如何识别这一点? 关于这件事我有两个不同的问题,也许他们之间有没有关系, 第一个: 我怎么能得到