使用opencv检测棋盘上方的手

时间:2018-07-11 10:44:12

标签: opencv computer-vision detection

我正在开发一个Android应用程序,用于基于一系列照片来分析国际象棋游戏。要处理图像,我正在使用OpenCV。我的问题是如何检测图片上有玩家的手?因为我想过滤那些照片,只分析上面只有棋盘的照片。

到目前为止,我设法得到了Canny,所以从这样的图像中 原始图片

我能够得到那个精明的人

但是我不知道下一步该怎么做...

我用来获取Canny的代码:

Mat gray, blur, cannyed;
cvtColor(img, gray, CV_BGR2GRAY);
GaussianBlur(gray, blur, Size(7, 7), 0, 0);
Canny(blur, cannyed, 50, 100, 3);

对于接下来要做什么以及可以使用哪些OpenCV功能,我将深表感谢。

4 个答案:

答案 0 :(得分:2)

您在国际象棋棋盘上的频谱非常好。一只手插进去,弄乱了黑白方格之间的常规过渡所建立的频率。尝试在周围移动一个更大的正方形(假设尺寸为4.5 x 4.5正方形),看看频率发生了什么。

如果您将一系列照片作为电影拍摄,则另一种方法是分析运动。取连续帧的差异(先对它们进行低通滤波)以检测运动。及时过滤运动(超过几帧)。然后对这些运动进行阈值处理以获得二进制图像。侵蚀二进制形状以过滤掉小的运动物体(噪声,国际象棋棋子),从而能够检测棋盘上是否有更大的运动形状(例如手)。

答案 1 :(得分:1)

在这里,在检测到Canny Edge之后,我尝试了水平和垂直线条提取过程的形态学操作。

 Mat horizontal = cannyed.clone();
    // Specify size on horizontal axis
    int horizontalsize = horizontal.cols / 60;
    // Create structure element for extracting horizontal lines through morphology operations
    Mat horizontalStructure = getStructuringElement(MORPH_RECT, Size(horizontalsize,1));
    erode(horizontal, horizontal, horizontalStructure, Point(-1, -1),2);
    dilate(horizontal, horizontal, horizontalStructure, Point(-1, -1),1);
    imshow("horizontal",horizontal);

    Mat vertical = cannyed.clone();
    // Specify size on horizontal axis
    int verticalsize = vertical.cols / 60;
    // Create structure element for extracting horizontal lines through morphology operations
    Mat verticalStructure = getStructuringElement(MORPH_RECT, Size(1,verticalsize));
    erode(vertical, vertical, verticalStructure, Point(-1, -1));
    dilate(vertical, vertical, verticalStructure, Point(-1, -1),2);
    imshow("vertical",vertical);

结果是, Horizontal Lines in the chess board

Horizontal Lines in the chess board

然后,从图中您可以看到两行之间有一个适当的间隔。出现手的区域在行中有更多的间隔。

在该位置,如果完成轮廓绘制,则可以检测到棋盘上的手(或任何物体)。

这有助于解决将任何物体放在国际象棋棋盘上的问题。

答案 2 :(得分:0)

非常感谢大家的建议。

所以我主要使用Gowthaman的方法解决了这个问题。首先,我使用他的代码生成垂直和水平线。然后,我将它们像这样组合:

Mat combined = vertical + horizontal; 

所以没有手的时候我会得到类似的东西

without hand

或者在有手的时候这样

with hand

接下来,我使用以下代码计算白色像素:

int GetPixelCount(Mat image, uchar color)
{
    int result = 0;

    for (int i = 0; i < image.rows; i++)
    {
        for (int j = 0; j < image.cols; j++)
        {
            if (image.at<uchar>(Point(j, i)) == color)
                result++;
        }
    }

    return result;
}

我对系列中的每张照片都这样做。第一张照片总是没有手,所以我使用它作为模板。如果当前照片的模板白色像素少于98%,那么我推断其中有手(或其他东西)。

这很可能不是一种最佳方法,并且有很多缺点,但是它非常简单,对我来说也很好:)

答案 3 :(得分:-1)

您如何考虑将图像转换为HSV颜色空间并搜索手的颜色。然后,您可以搜索轮廓,并且如果最大轮廓的大小大于您设置的值,则可以说图像上有一只手。我已经用您发布的图像制作了一个样本,并且可以对此图像进行处理,但是需要与其他人进行测试(可能会更改颜色范围)。

示例:

import cv2
import numpy as np

img = cv2.imread('chess.jpg')
kernel = np.ones((7,7),np.uint8)
erosion = cv2.erode(img,kernel,iterations = 1)
hsv = cv2.cvtColor(erosion, cv2.COLOR_BGR2HSV)
lower_skin = np.array([0,100,200])
upper_skin = np.array([10,255,255])
mask = cv2.inRange(hsv, lower_skin, upper_skin)
im, contours, hierarchy = cv2.findContours(mask,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
cnt = max(contours, key=cv2.contourArea)
size = cv2.contourArea(cnt)
if size > 300:
    x,y,w,h = cv2.boundingRect(cnt)
    cv2.rectangle(img,(x,y),(x+w,y+h),(0,0,255),2)
    print('Hand detected')
else:
    print('No hand detected')
cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果:

enter image description here

Hand detected

enter image description here

No hand detected