如何使用 OpenCV 在此图像中检测中国棋子?

c++ - 使用OpenCV检测棋盘中的中国棋子-LMLPHP

我试过使用 HoughCircles ,但没​​有找到圆圈。

Mat src = imread( "x.jpg", CV_LOAD_IMAGE_GRAYSCALE);
GaussianBlur( src, src, Size(9, 9), 2, 2 );

vector<Vec3f> circles;
HoughCircles( src, circles, CV_HOUGH_GRADIENT, 1, src.rows/16);
cout << circles.size() << endl;
// The output is: 0

也测试了 Blob 检测器,但结果不正确。
Mat im = imread( "x.jpg", IMREAD_GRAYSCALE );

vector<KeyPoint> kps;
SimpleBlobDetector().detect(im, kps);

Mat im_kps;
drawKeypoints( im, kps, im_kps, Scalar(0,0,255), DrawMatchesFlags::DRAW_RICH_KEYPOINTS );
imshow("keypoints", im_kps );
waitKey(0);

最佳答案

从图像 m 中分离红色时可能出现的一个问题是棋子与同样为红色的背景的混合。运行 inRange() 时,会发生这种情况:

c&#43;&#43; - 使用OpenCV检测棋盘中的中国棋子-LMLPHP

乍一看,很难分辨跳棋的位置!但是我们可以使用 膨胀 腐 eclipse 的技巧来去除次要部分(网格),同时保留重要部分(圆形检查器)。

这是用膨胀和腐 eclipse 来解决检查器问题的代码:

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>

using namespace cv;
using namespace std;

Mat getElement(int erosion_size)
{
  return getStructuringElement(cv::MORPH_ELLIPSE,
         cv::Size(2 * erosion_size + 1, 2 * erosion_size + 1),
         cv::Point(erosion_size, erosion_size) );
}
int main( )
{
    vector<vector<Point> > contours;
    //vector<Vec4i> hierarchy;
    //int largest_area,largest_contour,largest_contour_index;
    //RotatedRect bounding_ellipse;

     Mat image,dst,filtered;
     Mat a1,a2;

     //Color ranging red (from both left & right spectrums)
     image = imread("circles.jpg");
     cvtColor(image,filtered,CV_BGR2HSV);

     Scalar low = Scalar(0, 100, 50);
     Scalar up = Scalar(10, 255, 255);

     Scalar low2 = Scalar(160, 100, 50);
     Scalar up2 = Scalar(179, 255, 255);

     inRange(filtered, low2, up2, a1);
     inRange(filtered, low2, up2, a2);
     bitwise_or(a1,a2,filtered);

     imshow("troll", filtered);


     // Fill in small holes from Chinese lettering
     dilate(filtered,filtered,getElement(11));

     imshow("better", filtered);
     // Erode to remove minor (like square lines) objects
     erode(filtered,filtered,getElement(25));
     imshow("best",filtered);

     findContours(filtered, contours, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE);

     for( int i = 0; i< contours.size(); i++ )
     {
       //Only draw big contours, not minor details
        double area =contourArea( contours[i],false);
        if(area > 1500)
        {
          drawContours(image, contours, i, Scalar(0,255,0), 5);
        }
    }
     imshow( "Result window", image );

     waitKey(0);
     return 0;
}

解释:

1. 膨胀

我们从 膨胀 开始,它允许图像的较亮部分“扩展”到“较暗”部分。所以,在这里,我们将使用它来删除中文字母(所以当,在扩张时,我们不会在圆圈中间有大洞):

c&#43;&#43; - 使用OpenCV检测棋盘中的中国棋子-LMLPHP

2. 侵 eclipse

如您所见,现在圆圈已填满,我们可以继续 侵 eclipse 。我们需要扩大超过我们侵 eclipse 的数量,因为我们需要从图像中删除网格条。应用腐 eclipse ,我们只得到棋盘上的棋子(以及我们稍后将处理的一些噪音):

c&#43;&#43; - 使用OpenCV检测棋盘中的中国棋子-LMLPHP

3. 轮廓处理

现在,我们可以处理棋子了,但是我们需要过滤掉图像周围的噪声。为此,我们将根据侵 eclipse 结果运行 findContours(),但我们还将检查轮廓的区域,即 contourArea() 以确保它是我们的棋子。如果面积小于 1500,我们知道它是噪音,我们可以将其丢弃。否则,我们可以将其绘制到屏幕上。

c&#43;&#43; - 使用OpenCV检测棋盘中的中国棋子-LMLPHP

关于c++ - 使用OpenCV检测棋盘中的中国棋子,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34302693/

10-16 04:54