AHTcode
De Pontão Nós Digitais
Ir para navegaçãoIr para pesquisar
Aí está o código, na íntegra
Em Breve: More comments!
/* Programa esqueleto da AirHackTable */ #include "opencv/highgui.h" #include "opencv/cv.h" #include <stdio.h> using namespace cv; void pausef(void); class ColorHistogram { private: int histSize[3]; float hranges[2]; const float* ranges[3]; int channels[3]; public: ColorHistogram() { // Prepare arguments for a color histogram histSize[0]= histSize[1]= histSize[2]= 256; hranges[0]= 0.0; // BRG range hranges[1]= 255.0; ranges[0]= hranges; // all channels have the same range ranges[1]= hranges; ranges[2]= hranges; channels[0]= 0; // the three channels channels[1]= 1; channels[2]= 2; } cv::MatND getHistogram(const cv::Mat &image) { cv::MatND hist; // Compute histogram cv::calcHist(&image, 1, // histogram of 1 image only channels, // the channel used cv::Mat(), // no mask is used hist, // the resulting histogram 3, // it is a 3D histogram histSize, // number of bins ranges // pixel value range ); return hist; } // Computes the 1D Hue histogram with a mask. // BGR source image is converted to HSV // Pixels with low saturation are ignored cv::MatND getHueHistogram(const cv::Mat &image, int minSaturation=0) { cv::MatND hist; // Convert to HSV color space cv::Mat hsv; cv::cvtColor(image, hsv, CV_BGR2HSV); // Mask to be used (or not) cv::Mat mask; if (minSaturation>0) { // Spliting the 3 channels into 3 images std::vector<cv::Mat> v; cv::split(hsv,v); // Mask out the low saturated pixels cv::threshold(v[1],mask,minSaturation,255, cv::THRESH_BINARY); } // Prepare arguments for a 1D hue histogram hranges[0]= 0.0; hranges[1]= 180.0; channels[0]= 0; // the hue channel // Compute histogram cv::calcHist(&hsv, 1, // histogram of 1 image only channels, // the channel used mask, // binary mask hist, // the resulting histogram 1, // it is a 1D histogram histSize, // number of bins ranges // pixel value range ); return hist; } }; class ContentFinder { private: float hranges[2]; const float* ranges[3]; int channels[3]; float threshold; cv::MatND histogram; public: ContentFinder() : threshold(-1.0f) { ranges[0]= hranges; // all channels have same range ranges[1]= hranges; ranges[2]= hranges; } // Sets the threshold on histogram values [0,1] void setThreshold(float t) { threshold= t; } // Gets the threshold float getThreshold() { return threshold; } // Sets the reference histogram void setHistogram(const MatND& h) { histogram= h; cv::normalize(histogram,histogram,1.0); } Mat find(const cv::Mat& image) { Mat result; hranges[0]= 0.0; // range [0,255] hranges[1]= 255.0; channels[0]= 0; // the three channels channels[1]= 1; channels[2]= 2; cv::calcBackProject(&image, 1, // one image channels, // vector specifying what histogram dimensions belong to what image channels histogram, // the histogram we are using result, // the resulting back projection image ranges, // the range of values, for each dimension 255.0 // the scaling factor is chosen such that a histogram value of 1 maps to 255 ); // Threshold back projection to obtain a binary image if (threshold>0.0) cv::threshold(result, result, 255*threshold, 255, cv::THRESH_BINARY); return result; } Mat find(const cv::Mat& image, float minValue, float maxValue, int *channels, int dim) { cv::Mat result; hranges[0]= minValue; hranges[1]= maxValue; for (int i=0; i<dim; i++) this->channels[i]= channels[i]; // NOT USING THIS PART // if (isSparse) { // call the right function based on histogram type // // cv::calcBackProject(&image, // 1, // we only use one image at a time // channels, // vector specifying what histogram dimensions belong to what image channels // shistogram, // the histogram we are using // result, // the resulting back projection image // ranges, // the range of values, for each dimension // 255.0 // the scaling factor is chosen such that a histogram value of 1 maps to 255 // ); // // } else { cv::calcBackProject(&image, 1, // we only use one image at a time channels, // vector specifying what histogram dimensions belong to what image channels histogram, // the histogram we are using result, // the resulting back projection image ranges, // the range of values, for each dimension 255.0 // the scaling factor is chosen such that a histogram value of 1 maps to 255 ); // } // Threshold back projection to obtain a binary image if (threshold>0.0) cv::threshold(result, result, 255*threshold, 255, cv::THRESH_BINARY); return result; } }; // AirHackTable class AHT { private: // int pad; #define TAM 1 #define PAD 15 // amount of circles to be detected ContentFinder circleFinder; ColorHistogram hist; Point circleCenter; Point circleCenter2; void sharpen(Mat &image) { // Construct kernel (all entries initialized to 0) Mat kernel(3,3,CV_32F,Scalar(0)); // assigns kernel values kernel.at<float>(1,1)= 5.0; kernel.at<float>(0,1)= -1.0; kernel.at<float>(2,1)= -1.0; kernel.at<float>(1,0)= -1.0; kernel.at<float>(1,2)= -1.0; // filter the image filter2D( image, image, image.depth(), kernel); } void colorReduce(Mat &image, int div=64) { int nl = image.rows; // number of lines // total number of elements per line int nc = image.cols * image.channels(); for (int j = 0; j < nl; j++) { // get the address of row j uchar* data = image.ptr<uchar>(j); for (int i = 0; i < nc; i++) { data[i] = data[i]/div*div + div/2; } // end of line } } public: Mat process(Mat &image) { Mat result, thres; flip( image, image, 1 ); sharpen( image ); colorReduce( image, 32 ); cvtColor( image, result, CV_RGB2GRAY ); equalizeHist( result, result ); // Canny( result, result, 0, 255); GaussianBlur( result, result, Size(7,7) , 3); // threshold( result, thres, 110, 255, CV_THRESH_BINARY); // result += thres/10; return result; } // old version, not using anymore // it is still here so I can use its code void findCircles(Mat &image, Mat result, int minSaturation=0) { circleFinder.setThreshold(0.05f); // pad = 15; double count, sx[TAM] = { 0 }, sy[TAM] = { 0 }; // holds the detected circles vector<Vec3f> circles; HoughCircles( result( Rect( PAD, PAD, result.cols-PAD, result.rows-PAD) ), circles, CV_HOUGH_GRADIENT, 1.65, 32); // TODO // To be improved for( size_t i = 0, count = 0; i < circles.size() && count < TAM; i++, count++ ) { Point center(cvRound(circles[i][0]), cvRound(circles[i][1])); // if ( (center.x - sx[count] < 5) && ( center.y - sy[count] < 5) ) { Mat ROI = image( Rect( center.x-PAD, center.y-PAD, 2*PAD, 2*PAD ) ); circleFinder.setHistogram(hist.getHueHistogram(ROI, minSaturation)); // hist = f.find(image); // hist += f.find(image); circle( image, Point(center.x+PAD, center.y+PAD) , 19, 255, 2 ); } sx[count] = center.x; sy[count] = center.y; } } void getCircles(Mat image, Mat result, int minSaturation=0) { // holds the detected circles vector<Vec3f> circles; HoughCircles( result( Rect( PAD, PAD, result.cols-PAD, result.rows-PAD) ), circles, CV_HOUGH_GRADIENT, 1.65, 32); // TODO if( circles.size() ) { Point center(cvRound(circles[0][0]), cvRound(circles[0][1])); Mat ROI = image( Rect( center.x-PAD, center.y-PAD, 2*PAD, 2*PAD ) ); circleFinder.setHistogram(hist.getHueHistogram(ROI, minSaturation)); circleCenter = center; } } // not using yet void nextPosition(Mat image, int minSaturation=0) { Mat hsv; // Convert to HSV space cvtColor( image, hsv, CV_BGR2HSV ); std::vector<Mat> v; // Split the image split( hsv, v ); // Identify pixels with low saturation threshold( v[1], v[1], minSaturation, 255, THRESH_BINARY ); int ch[1]={0}; // Get back-projection of hue histogram Mat result = circleFinder.find( hsv, 0.0f, 180.0f, ch,1 ); // Eliminate low stauration pixels bitwise_and( result, v[1], result ); Rect rect(circleCenter.x+PAD,circleCenter.y+PAD,1,1); // rectangle(image, rect, cv::Scalar(0,0,255)); TermCriteria criteria( cv::TermCriteria::MAX_ITER, 10, 0.01 ); meanShift( result, rect, criteria ); circleCenter2.x = rect.x; circleCenter2.y = rect.y; // return result; } void drawCircle(Mat &image) { if( circleCenter.x != 0 ) circle( image, Point(circleCenter.x+PAD, circleCenter.y+PAD) , 19, 255, 2 ); if( circleCenter2.x != 0 ) circle( image, Point(circleCenter2.x, circleCenter2.y) , 19, 0, 2 ); } }; int main( int argc, char** argv ) { char c; int minSat = 65; namedWindow( "player", 0 ); // namedWindow( "mod", 0 ); // namedWindow( "Histogram", 0 ); CvCapture *cam; if( argc != 2 ) cam = cvCreateCameraCapture(0); // else // cam.open( string(argv[1]) ) Mat frame, modframe; AHT image; while(1) { // gets the next frame frame = cvQueryFrame(cam); if(!frame.data) break; modframe = image.process(frame); // look for the circles // image.findCircles(frame, modframe); if( c == 'g' ) image.getCircles(frame, modframe, minSat); if( c == 'n' ) image.nextPosition(frame, minSat); image.drawCircle(frame); // show results // imshow("Histogram", hist); imshow( "player", frame ); // imshow( "mod", modframe ); c = cvWaitKey(3); // c == ESC if( c == 27 ) break; else if( c == ' ' || c == 'p' ) pausef(); } destroyWindow("player"); // destroyWindow("mod"); // destroyWindow("Histogram"); return 0; } void pausef() { char c = 0; while( c != 'p' && c != ' ' ) c = cvWaitKey(0); }
Pode comentar, se precisar de me contatar veja meus contatos aqui