# recognise colours in 3x3 grid Hi all,

I'm just starting, so this is a very high level question...

Is it possible to use OpenCV for recognising basic colours in a 3x3 grid? Imagine a rubik's cube, you take a picture of one of the sides and this picture is then either

• compared to a set of pictures showing all possible combinations and one of them is matched
• analyzed and the colours are directly identified, i.e. upper left corner is yellow, middle is red...

Do you think something like this is possible in OpenCV and if yes, can you give me first hints what to start with?

Thanks a lot!

edit retag close merge delete

Sort by » oldest newest most voted there is some solutions on the net about "Solving Rubik's Cube" or "Locating Rubik's Cube" using OpenCV like this. Maybe you can find better code sample.But i want to share a simple code to show with just a simple OpenCV code you will get some result like    the code is modified version of squares.cpp

#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"

using namespace cv;
using namespace std;

// helper function:
// finds a cosine of angle between vectors
// from pt0->pt1 and from pt0->pt2
static double angle( Point pt1, Point pt2, Point pt0 )
{
double dx1 = pt1.x - pt0.x;
double dy1 = pt1.y - pt0.y;
double dx2 = pt2.x - pt0.x;
double dy2 = pt2.y - pt0.y;
return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
}

static void drawSquares( Mat& image, const vector<vector<Point> >& squares )
{
for( size_t i = 0; i < squares.size(); i++ )
{
const Point* p = &squares[i];
int n = (int)squares[i].size();
int shift = 1;

Rect r=boundingRect( Mat(squares[i]));
r.x = r.x + r.width / 4;
r.y = r.y + r.height / 4;
r.width = r.width / 2;
r.height = r.height / 2;

Mat roi = image(r);
Scalar color = mean(roi);
polylines(image, &p, &n, 1, true, color, 2, LINE_AA, shift);

Point center( r.x + r.width/2, r.y + r.height/2 );
ellipse( image, center, Size( r.width/2, r.height/2), 0, 0, 360, color, 2, LINE_AA );
}
}

// returns sequence of squares detected on the image.
// the sequence is stored in the specified memory storage
static void findSquares( const Mat& image, vector<vector<Point> >& squares , bool inv=false)
{
squares.clear();

Mat gray,gray0;

vector<vector<Point> > contours;

cvtColor(image,gray0,COLOR_BGR2GRAY);
GaussianBlur(gray0, gray0, Size(7,7), 1.5, 1.5);
Canny(gray0,gray, 0, 30, 3);

// find contours and store them all as a list
findContours(gray, contours, RETR_LIST, CHAIN_APPROX_SIMPLE);

vector<Point> approx;

// test each contour
for( size_t i = 0; i < contours.size(); i++ )
{
// approximate contour with accuracy proportional
// to the contour perimeter
approxPolyDP(Mat(contours[i]), approx, 9, true);

// square contours should have 4 vertices after approximation
// relatively large area (to filter out noisy contours)
// and be convex.
// Note: absolute value of an area is used because
// area may be positive or negative - in accordance with the
// contour orientation
if( approx.size() == 4 &&
fabs(contourArea(Mat(approx))) > 5 &&
isContourConvex(Mat(approx)) )
{
double maxCosine = 0;

for( int j = 2; j < 5; j++ )
{
// find the maximum cosine of the angle between joint edges
double cosine = fabs(angle(approx[j%4], approx[j-2], approx[j-1]));
maxCosine = MAX(maxCosine, cosine);
}

// if cosines of all angles are small
// (all angles are ~90 degree) then write quandrange
// vertices to resultant sequence
if( maxCosine < 0.3 )
squares.push_back(approx);
}
}
}

int main()
{
VideoCapture cap(0); // opens default webcam

if (!cap.isOpened())
{
return -1;
}

Mat frame;
vector<vector<Point> > squares;

for (;;)
{
cap >> frame;

if (frame.empty())
{
return -1;
}
findSquares(frame, squares);
drawSquares(frame, squares);
imshow("Rubic Detection Demo", frame);
waitKey ...
more

DId you edit the code yourself or did you grab it from somewhere? If so please provide the original link to give that person the credit that he deserves :)

2

How can i save the value of colors of each side in a text file? Like = Red Green Green Green Green Green Yellow Yellow Yellow

Yes this is possible with OpenCV. You will have to look at

1. Making sure that you compensate for camera deformation.
2. Defining the area of the rubics cube itself, by trying to find its outer boundaries.
3. Then taking the corner points to transform the image to a standard squared area.
4. Now find the crossing points of the seperate elements, defining individual regions of interest.
5. Start doing color analysis on each position.

If you're just starting OpenCV, start by going through the basic tutorials first, then this might be a very nice project to start of with!

more

1

Wow, that was a really quick answer! Thanks a lot for your hints - I'll give it a try, really sounds promising!

That is because I am a forum admin and I had to accept your answer. You were lucky I was just browsing the website :)

I've been working on a mindstorms robot that takes pics of a rubiks cube via webcam and then solves it. For the question you ask, I broke it down into two problems: - find the cube in an image..openCV is awesome for this - take the RGB values for all of the squares you found and reduce each of those to one of the 6 colors of the cube. There isn't much use for OpenCV on this part

The code for the first part is at https://github.com/dwalton76/rubiks-c... and the code for the second part is at https://github.com/dwalton76/rubiks-c...

I did a blog post on how rubiks-cube-tracker works http://programmablebrick.blogspot.com...

You can run it on your laptop and hold the cube up to the webcam to scan the six sides and get a solution https://www.youtube.com/watch?v=3tWnl...

This is all open source, feel free to use it and/or contribute to it.

more

Official site

GitHub

Wiki

Documentation