Dices Result Recognition

Description

The goal of this project is to implement algorithm that finds dots on dices. Motivation was idea / question how to create home-made random number generator? We can throw dices and our application will be able to recognize summary value on dices.

This program uses fitEllipse() function to find dots on dices. The basics steps are as follows:

Process

1. Open video stream
```CvCapture* capture = cvCaptureFromCAM( CV_CAP_ANY );
```
2. For the whole stream we create single frame
```IplImage* frame = cvQueryFrame( capture );
```
3. Invert color
```adaptiveThreshold(image, bimage, 255, ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, 15, -10);
```
5. We can use morphological operations (dilatation, erosion) to expand/minimize contours
6. To find circles we use following:
```Mat pointsf;
Mat(contours[i]).convertTo(pointsf, CV_32F);
RotatedRect box = fitEllipse(pointsf);
```
7. If difference between box.size.width and box.size.height is lower than treshold, we consider ellipse as circle.
8. At this point we have a lot of “circles”. An experimenting helped us to determine, which circle in the picture is real point on dice. Based on size of real dices points we can isolate only real dices points.

Example of process

Original grayscale image

Inverted colors

Histogram of points size

Lots of custom settings

RESULT!

Using custom settings we are able to improve results in specific situations.

```findContours(bimage, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);

Vector<pair<RotatedRect*, int>> vec, finalVec;
Mat cimage = Mat::zeros(bimage.size(), CV_8UC3);
int i;
int w, h, wAhThr, angleThr, centerThr;
int  hwDifferenceThreshold, histThreshold;
centerThr = settCenterThr;
wAhThr = settwAhThr;
hwDifferenceThreshold = settHWdifferenceThr;
histThreshold = settHistogramThr;

for(i = 0; i < contours.size(); i++)
{
size_t count = contours[i].size();
if( count > 50 || count  < 6)
continue;

Mat pointsf;
Mat(contours[i]).convertTo(pointsf, CV_32F);
RotatedRect box = fitEllipse(pointsf);

w = box.size.width;
h = box.size.height;

int hwDifference = abs(h - w);
if (hwDifference > hwDifferenceThreshold)
continue;

if (w < wAhThr || h < wAhThr)
continue;

vec.push_back(pair<RotatedRect*, int>(new RotatedRect(box), i));
}

int asdf = vec.size();
Vector<pair<RotatedRect* ,int>>::iterator it ,iend, it2;
int MAXHIST = 200;
int* histVals = new int[MAXHIST];
for (int i = 0; i < MAXHIST; i++)
histVals[i] = 0;

int histIter = 0;
RotatedRect * box;
RotatedRect * box2;
int maxWidth = 0;
int distanceOfCenters;
for (it = vec.begin(), iend = vec.end(); it != iend; it++)
{
box = (it->first);
for (it2 = it + 1; it2 != iend; it2++)
{
box2 = (it2->first);
distanceOfCenters = (int)std::sqrt((box->center.x - box2->center.x) * (box->center.x - box2->center.x) + (box->center.y - box2->center.y)  * (box->center.y - box2->center.y));
if (distanceOfCenters < centerThr)
{
if (box->size.width > box2->size.width)
it2->second = -1;
else
it->second = -1;
break;
}

}
}
```