Soccer is pingpang ball, since it is semi-transparent and has black letter on it, it is very hard to filter colour under OpenCV, so I painted it with water colour.
Same with goal, to easy distinguish, painted it with blue water colour.
OpenCV is very powerful, it has plenty of functions for object detection. The main idea is, with smart phone camera, convert image to grey under HSV space, then filter colour, blur it then detect circle for soccer and rectangle for goal.
Following is source code for visual soccer and goal detection under Android with JNI c code.
Using OpenCV library under Android, ball is coloured to red and net is coloured to blue.
int detectDoor(Mat & img_rgba, int & door_x, int & door_y)
{
Mat img_temp;
Mat img_work;
Mat img_gray;
int sel_id;
int max_area;
Mat img_3;
Mat kernel_ero = getStructuringElement(MORPH_RECT, Size(2,2));
int h;
int s;
int v;
door_x = 0;
door_y = 0;
h = 237/2;
s = 100*2 + 55;
v = 25*2 + 55;
cv::cvtColor(img_rgba, img_temp, CV_RGB2HSV); // convert to HSV
inRange(img_temp, Scalar(266/2-20, 0, 0), Scalar(266/2+20, 255, 255), img_work); // filter color
cv::blur(img_work, img_gray, Size(30, 30));
threshold(img_gray, img_gray, 100, 255, CV_THRESH_BINARY);
erode(img_gray, img_gray, kernel_ero);
Size sz;
vector<vector<Point> > contours;
vector<vector<Point> > contours0;
vector<Vec4i> hierarchy;
findContours( img_gray, contours0, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
int idx = 0;
sel_id = 0;
max_area = 0;
for( idx = 0; idx < contours0.size(); idx++ )
{
Rect r = boundingRect(contours0[idx]);
Scalar color( 255, 0, 0 );
if(hierarchy[idx][2] < 0) //Check if there is a child contour
rectangle(img_rgba,Point(r.x-10,r.y-10), Point(r.x+r.width+10,r.y+r.height+10), Scalar(0,0,255),2,8,0); //Opened contour
else
rectangle(img_rgba,Point(r.x-10,r.y-10), Point(r.x+r.width+10,r.y+r.height+10), Scalar(0,255,0),2,8,0); //closed contour
if( max_area < r.width * r.height)
{
max_area = r.width * r.height;
sel_id = idx;
}
}
// choose area > 400
if( max_area > 400 )
{
Rect r = boundingRect(contours0[sel_id]);
door_x = r.x + r.width/2;
door_y = r.y + r.height/2;
circle(img_rgba,Point(door_x,door_y),20, Scalar(255,0,0), 3, 8, 0); //closed contour
}
return 0;
}
JNIEXPORT jintArray JNICALL Java_com_example_balltrace_BallTrace_BallDetect(JNIEnv* env, jobject thiz,
jint width, jint height, jlong yuv, jlong rgba, jlong outPtr)
{
jint outArray[5];
Mat mGray = *((Mat*)yuv);
Mat mRgba = *((Mat*)rgba); // original camera image
int door_x = 0;
int door_y = 0;
Mat hsv_frame;
outArray[0] = 0;
outArray[1] = 0;
outArray[2] = 0;
outArray[3] = -1; // door rect center X
outArray[4] = -1; // door rect center y
detectDoor(mRgba, door_x, door_y);
outArray[3] = door_x;
outArray[4] = door_y;
//Mat thresholded;
cv::Mat* thresholded = new cv::Mat(cv::Size(width, height), CV_8UC1);
cv::Rect roi( cv::Point( 0, 0 ), Size(width, height) );
CvSize size = cvSize(width, height);
cvtColor(mRgba, hsv_frame, CV_RGB2HSV);
inRange(hsv_frame, Scalar(1, 80, 80), Scalar(7, 250, 250), *thresholded);
GaussianBlur(*thresholded, *thresholded, Size(9,9), 0, 0);
vector<Vec3f> circles;
HoughCircles(*thresholded, circles, CV_HOUGH_GRADIENT,1.5, height/4, 100, 40, 15, 80 );
for( size_t i = 0; i < circles.size(); i++ )
{
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
if( radius < 5 )
continue;
// draw the circle center
circle( mRgba, center, 3, Scalar(0,255,0), -1, 8, 0 );
// draw the circle outline
circle( mRgba, center, radius, Scalar(0,0,255), 3, 8, 0 );
outArray[0] = cvRound(circles[i][0]);
outArray[1] = cvRound(circles[i][1]);
outArray[2] = radius;
break;
}
delete thresholded;
jintArray retArray = env->NewIntArray(5);
env->SetIntArrayRegion(retArray, 0 , 5, outArray);
return retArray;
}
No comments:
Post a Comment