检测图像中的 4 的符号是什么的最佳方法是什么?

问题描述 投票:0回答:1

我有一块板上有网格,每个单元格都可以有其中一张“卡片”,或者它可以是空的。

Card0/BlueCard1/White

Card2/YellowCard3/Gourney

我已经完成了对板的改造,这样我就可以单独地切出每个单元格,但然后我必须查看每个单元格并给出卡的值。 我尝试比较 histogramstemplate 匹配,但是相对来说 bad 所以我尝试获取图像的平均 HSV 值,看看色相、饱和度和值是否在预定义的范围内,但这也给出了我遇到了一些问题,例如有时白卡的色调为 350,然后为 1。

这个问题有好的解决办法吗?

image-processing detection
1个回答
0
投票

我通过查看 HSV 色彩空间中的图像并计算图像中红色、黄色和蓝色像素的百分比并做出相应的选择来解决这个问题。首先,我寻找黄色,如果找到,那就是第三张图像。然后我寻找布鲁斯,如果没有找到,那就是第二张图片。然后我寻找红色,如果找到的话,那就是第一张图片。不然一定是最后一张了:

#!/usr/bin/env python3

import cv2 as cv
import numpy as np

def detectCard(im):
    """ Detect which of 4 cards was passed as parameter """
    nPixels = im.shape[0] * im.shape[1]
    # Convert to HSV colourspace
    HSV = cv.cvtColor(im, cv.COLOR_BGR2HSV)

    # Identify yellow pixels - these will be around Hue=30, and fairly saturated
    yellowLo   = np.array([20, 50, 0], np.uint8)
    yellowHi   = np.array([40, 255, 255], np.uint8)
    yellowMask = cv.inRange(HSV, yellowLo, yellowHi)
    yellowPcnt = np.count_nonzero(yellowMask)*100/nPixels
    cv.imwrite('DEBUG-yellowMask.png', yellowMask)

    # Identify blue pixels - these will be around Hue=120, and fairly saturated
    blueLo   = np.array([110, 50, 0], np.uint8)
    blueHi   = np.array([130, 255, 255], np.uint8)
    blueMask = cv.inRange(HSV, blueLo, blueHi)
    bluePcnt = np.count_nonzero(blueMask)*100/nPixels
    cv.imwrite('DEBUG-blueMask.png',blueMask)
   
    # Identify red pixels - these will be around Hue=170..180 or Hue=0..10 and fairly saturated
    redLo   = np.array([170, 50, 0], np.uint8)
    redHi   = np.array([180, 255, 255], np.uint8)
    redMask = cv.inRange(HSV, redLo, redHi)
    redLo   = np.array([0, 50, 0], np.uint8)
    redHi   = np.array([10, 255, 255], np.uint8)
    redMask2= cv.inRange(HSV, redLo, redHi)
    redMask = np.bitwise_or(redMask, redMask2)
    redPcnt = np.count_nonzero(redMask)*100/nPixels
    cv.imwrite('DEBUG-redMask.png',redMask)

    # Share percentages with caller
    print(f' {yellowPcnt=:.2f}, {bluePcnt=:.2f}, {redPcnt=:.2f}')
   
    # Note these tests could be done sooner to avoid so much calculation 
    # If plenty of yellow pixels, return "yellow"
    if yellowPcnt > 30:
        return "yellow"
    if bluePcnt < 10:
        return "red cross on white background"
    if redPcnt > 10:
        return "red cross on blue circle"
    return "robocar"

# Main program and test driver
for i in range(1,5):
    name = f'{i}.png'
    print(f'Analysing: {name}...')
    im = cv.imread(name)
    print(f'{name}: detected as {detectCard(im)}')

以下是结果,如果将输入图像命名为

1.png
为左上角,
2.png
为右上角,
3.png
为左下角,
4.png
为右下角:

Analysing: 1.png...
 yellowPcnt=0.06, bluePcnt=14.19, redPcnt=31.91
1.png: detected as red cross on blue circle
Analysing: 2.png...
 yellowPcnt=0.00, bluePcnt=0.00, redPcnt=41.77
2.png: detected as red cross on white background
Analysing: 3.png...
 yellowPcnt=58.07, bluePcnt=0.09, redPcnt=1.26
3.png: detected as yellow
Analysing: 4.png...
 yellowPcnt=5.91, bluePcnt=18.90, redPcnt=0.37
4.png: detected as robocar
© www.soinside.com 2019 - 2024. All rights reserved.