2015-05-26 47 views
3

我想要检测Rubiks立方体的颜色。这就是我想要的:Link
我能够识别OpenCV的findContours函数的9个颜色的字段。
这是我的代码:如何在图像中选择正确的矩形?

Mat input = new Mat(); //The image 
Mat blur = new Mat(); 
Mat canny = new Mat(); 

Imgproc.GaussianBlur(input, blur, new Size(3,3), 1.5); //GaussianBlur to reduce noise 

Imgproc.Canny(blur, canny, 60, 70); //Canny to detect the edges 
Imgproc.GaussianBlur(canny, canny, new Size(3,3), 1.5); //Again GaussianBlur to reduce noise 

List<MatOfPoint> contours = new ArrayList<>(); 
Mat hierachy = new Mat(); 

Imgproc.findContours(canny, contours, hierachy, Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE); //Find contours 

List<MatOfPoint2f> approxedShapes = new ArrayList<>(); 
for(MatOfPoint point : contours){ 
    double area = Imgproc.contourArea(point); 
    if(area > 1000){ 
     MatOfPoint2f shape = new MatOfPoint2f(point.toArray()); 
     MatOfPoint2f approxedShape = new MatOfPoint2f(); 

     double epsilon = Imgproc.arcLength(shape, true)/10; 

     Imgproc.approxPolyDP(shape, approxedShape, epsilon, true); //"Smooth" the edges with approxPolyDP 
     approxedShapes.add(approxedShape); 
    } 
} 

//Visualisation 
for(MatOfPoint2f point : approxedShapes){ 
    RotatedRect rect = Imgproc.minAreaRect(new MatOfPoint2f(point.toArray())); 
    Imgproc.circle(input, rect.center, 5, new Scalar(0, 0, 255)); 

    for(Point p : point.toArray()){ 
     Imgproc.circle(input, p, 5, new Scalar(0,255,0)); 
    } 
} 

这是 “原始” 的源图像:

Image

它产生此输出(绿色圆圈:角部;蓝色圆圈:矩形的中心) :

Image

正如你所看到的,也有更多的DETE我想获得点数组中的九个中点。
我该如何选择合适的?
希望你能明白我的意思

+0

您是否可以上传您的输入图像而无需任何后期处理?以便我们可以尝试我们的方法? –

回答

2

我已经写了代码在OpenCV中做到这一点。

基本的过程就像你的一样,找到等高线,然后除去小的非凸形轮廓。

在这之后,你可以在你的轮廓迭代,为每一个执行以下操作:

1. Sort the border pixels in ascending order using Y then X coords 
2. Iterate across the points. For each Y, add all points between each X and the next X to a vector. You now have a vector of all points contained within the vector. You can also use this to calculate the centroid and to calculate the mean RGB colour as below: 

一些示例代码如下但是注意,它是不完全的,它应该给你一个想法应该。

void meanColourOfContour(const Mat& frame, vector<Point> contour, Vec3b& colour, vector<Point>& pointsInContour) { 
    sort(contour.begin(), contour.end(), pointSorter); 


    // 
    // Mean RGB values 
    // 
    int rsum = 0; 
    int gsum = 0; 
    int bsum = 0; 

    int index = 0; 
    Point lastP = contour[index++]; 
    pointsInContour.push_back(lastP); 

    Vec3b rgbValue = frame.at<Vec3b>(lastP); 
    rsum += rgbValue[0]; 
    gsum += rgbValue[1]; 
    bsum += rgbValue[2]; 

    int currentRow = lastP.y; 
    int lastX = lastP.x; 

    // For all remaining points in contour 
    while(index < contour.size()) { 
     Point nextP = contour[index]; 

     // Save it 
     pointsInContour.push_back(nextP); 

     // If we're on the same row, add in values of intervening points 
     if(nextP.y == currentRow) { 
      for(int x = lastX; x < nextP.x; x++) { 
       Point p(x, currentRow); 
       pointsInContour.push_back(p); 
       rgbValue = frame.at<Vec3b>(p); 
       rsum += rgbValue[0]; 
       gsum += rgbValue[1]; 
       bsum += rgbValue[2]; 
      } 
     } 
     // Add nextP 
     rgbValue = frame.at<Vec3b>(nextP); 
     rsum += rgbValue[0]; 
     gsum += rgbValue[1]; 
     bsum += rgbValue[2]; 

     lastX = nextP.x; 
     currentRow = nextP.y; 
     index++; 
    } 

    // Calculate mean 
    size_t pointCount = pointsInContour.size(); 
    colour =Vec3b(rsum/pointCount, gsum/pointCount, bsum/pointCount); 
} 


void extractFacelets(const Mat& frame, vector<tFacelet>& facelets) { 
    // Convert to Grey 
    Mat greyFrame; 
    cvtColor(frame, greyFrame, CV_BGR2GRAY); 
    blur(greyFrame, greyFrame, Size(3,3)); 

    // Canny and find contours 
    Mat cannyOut; 
    Canny(greyFrame, cannyOut, 100, 200); 

    vector<vector<Point>> contours; 
    vector<Vec4i> hierarchy; 
    findContours(cannyOut, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE); 

    // Filter out non convex contours 
    for(int i=contours.size()-1; i>=0; i--) { 
     if(contourArea(contours[i]) < 400) { 
      contours.erase(contours.begin()+i); 
     } 
    } 

    // For each contour, calculate mean RGB and plot in output 
    int cindex = 0; 
    for(auto iter = contours.begin(); iter != contours.end(); iter ++) { 

     // Sort points in contour on ascending Y then X coord 
     vector<Point> contour = (vector<Point>)*iter; 
     vector<Vec3b> meanColours; 

     Vec3b meanColour; 
     vector<Point> pointsInContour; 
     meanColourOfContour(frame, contour, meanColour, pointsInContour); 

     meanColours.push_back(meanColour); 

     long x=0; long y=0; 
     for(auto iter=pointsInContour.begin(); iter != pointsInContour.end(); iter++) { 
      Point p = (Point) *iter; 
      x += p.x; 
      y += p.y; 
     } 

     tFacelet f; 
     f.centroid.x = (int) (x/pointsInContour.size()); 
     f.centroid.y = (int) (y/pointsInContour.size()); 
     f.colour = meanColour; 
     f.visible = true; 
     facelets.push_back(f); 
    } 

}