/** @function doHarris */ int Panorama::doHarris() { Mat R; Mat Rtemp; // Corner Response function Mat Ix, Iy, Ixy, Ix2, Iy2; // the second moment eigenvalues function double maxValtemp, minValtemp; double minVal; double maxVal; int sigma = 3; // Gaussian sigma float k = 0.04; // the alpha of Response function int aperture_size =3, block_size = 3; double scale = 1.0; // parameters of sobel first order derivative. char* window = "Harris."; // the name of Harris result ///////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////// cout << "Processing Harris Corner Detector..." << endl; /* Initialize the corner response function and the temp mat */ R = Mat::zeros( srcGray.size(), CV_32FC1 ); Rtemp = Mat::zeros( srcGray.size(), CV_32FC1 ); /* Use Sobel function to calculate the first order derivative of both x and y */ Sobel( srcGray, Ix, CV_32F, 1, 0, aperture_size, scale, 0, BORDER_DEFAULT ); Sobel( srcGray, Iy, CV_32F, 0, 1, aperture_size, scale, 0, BORDER_DEFAULT ); /* Calculate the Gaussian Derivative */ GaussianBlur(Iy, Iy, Size(block_size, block_size), sigma, 0 ,BORDER_DEFAULT); GaussianBlur(Ix, Ix, Size(block_size, block_size), sigma, 0 ,BORDER_DEFAULT); /* Calculate the square of each intensity */ pow(Ix,2,Ix2); pow(Iy,2,Iy2); /* Calculate the Gaussian Derivative */ GaussianBlur(Iy2, Iy2, Size(block_size, block_size), sigma, 0 ,BORDER_DEFAULT); GaussianBlur(Ix2, Ix2, Size(block_size, block_size), sigma, 0 ,BORDER_DEFAULT); /* Calculate the Corner Response function */ for( int j = 0; j < srcGray.rows; j++ ) { for( int i = 0; i < srcGray.cols; i++ ) { float lambda_1 = Ix2.at<float>( j, i, 0); float lambda_2 = Iy2.at<float>( j, i, 0); Rtemp.at<float>(j, i, 0) = lambda_1 * lambda_2 - k * pow( ( lambda_1 + lambda_2 ), 2 ); } } minMaxLoc( Rtemp, &minValtemp, &maxValtemp, 0, 0, Mat() ); /* Normalize Corner Response function as the maxium value is 1 */ for( int j = 0; j < srcGray.rows; j++ ) { for( int i = 0; i < srcGray.cols; i++ ) { R.at<float>(j, i) = 1 / maxValtemp * Rtemp.at<float>(j, i, 0); } } /* Find local maxima of response function (nonmaximum suppression)*/ minMaxLoc( R, &minVal, &maxVal, 0, 0, Mat() ); /* Create Window */ namedWindow( window, CV_WINDOW_AUTOSIZE ); int currentLevel = 5; int maxLevel = 100; double threshold = ( maxVal - minVal ) * currentLevel/maxLevel ; for( int j = 0; j < srcGray.rows; j++ ) { for( int i = 0; i < srcGray.cols; i++ ) { if( R.at<float>(j,i) > threshold) { circle( srcCopy, Point(i,j), 4, Scalar(255,255,255), 0, 0, 0 ); } } } imshow( window, srcCopy ); /* delete &minVal; delete &maxVal; delete &maxValtemp; delete &minValtemp; delete &R; delete &Rtemp; delete &Ix; delete &Iy; delete &Ix2; delete &Iy2; delete &Ixy; */ return(0); }
void ProcessingThread::run() { while(1) { ///////////////////////////////// // Stop thread if stopped=TRUE // ///////////////////////////////// stoppedMutex.lock(); if (stopped) { stopped=false; stoppedMutex.unlock(); break; } stoppedMutex.unlock(); ///////////////////////////////// ///////////////////////////////// // Save processing time processingTime=t.elapsed(); // Start timer (used to calculate processing rate) t.start(); // Get frame from queue, store in currentFrame, set ROI currentFrame=Mat(imageBuffer->getFrame(),currentROI); updateMembersMutex.lock(); /////////////////// // PERFORM TASKS // /////////////////// // Note: ROI changes will take effect on next frame if(resetROIFlag) resetROI(); else if(setROIFlag) setROI(); //////////////////////////////////// // PERFORM IMAGE PROCESSING BELOW // //////////////////////////////////// // Grayscale conversion if(grayscaleOn) cvtColor(currentFrame,currentFrameGrayscale,CV_BGR2GRAY); // Smooth (in-place operations) if(smoothOn) { if(grayscaleOn) { switch(smoothType) { // BLUR case 0: blur(currentFrameGrayscale,currentFrameGrayscale,Size(smoothParam1,smoothParam2)); break; // GAUSSIAN case 1: GaussianBlur(currentFrameGrayscale,currentFrameGrayscale,Size(smoothParam1,smoothParam2),smoothParam3,smoothParam4); break; // MEDIAN case 2: medianBlur(currentFrameGrayscale,currentFrameGrayscale,smoothParam1); break; } } else { switch(smoothType) { // BLUR case 0: blur(currentFrame,currentFrame,Size(smoothParam1,smoothParam2)); break; // GAUSSIAN case 1: GaussianBlur(currentFrame,currentFrame,Size(smoothParam1,smoothParam2),smoothParam3,smoothParam4); break; // MEDIAN case 2: medianBlur(currentFrame,currentFrame,smoothParam1); break; } } } // Dilate if(dilateOn) { if(grayscaleOn) dilate(currentFrameGrayscale,currentFrameGrayscale,Mat(),Point(-1,-1),dilateNumberOfIterations); else dilate(currentFrame,currentFrame,Mat(),Point(-1,-1),dilateNumberOfIterations); } // Erode if(erodeOn) { if(grayscaleOn) erode(currentFrameGrayscale,currentFrameGrayscale,Mat(),Point(-1,-1),erodeNumberOfIterations); else erode(currentFrame,currentFrame,Mat(),Point(-1,-1),erodeNumberOfIterations); } // Flip if(flipOn) { if(grayscaleOn) flip(currentFrameGrayscale,currentFrameGrayscale,flipCode); else flip(currentFrame,currentFrame,flipCode); } // Canny edge detection if(cannyOn) { // Frame must be converted to grayscale first if grayscale conversion is OFF if(!grayscaleOn) cvtColor(currentFrame,currentFrameGrayscale,CV_BGR2GRAY); Canny(currentFrameGrayscale,currentFrameGrayscale, cannyThreshold1,cannyThreshold2, cannyApertureSize,cannyL2gradient); } //////////////////////////////////// // PERFORM IMAGE PROCESSING ABOVE // //////////////////////////////////// // Convert Mat to QImage: Show grayscale frame [if either Grayscale or Canny processing modes are ON] if(grayscaleOn||cannyOn) frame=MatToQImage(currentFrameGrayscale); // Convert Mat to QImage: Show BGR frame else frame=MatToQImage(currentFrame); updateMembersMutex.unlock(); // Update statistics updateFPS(processingTime); currentSizeOfBuffer=imageBuffer->getSizeOfImageBuffer(); // Inform GUI thread of new frame (QImage) emit newFrame(frame); } qDebug() << "Stopping processing thread..."; }
void FindContour::singleCellDetection(const Mat &img, vector<Point> &cir_org, Mat &dispImg1, Mat &dispImg2, int &area, int &perimeter, Point2f &ctroid, float &shape, Mat &cell_alpha, // only the area inside cell (without background) vector<Point> &smooth_contour_curve, // relative position (without counting rect.x and rect.y) vector<Point> &smooth_contour_curve_abs, // absolut position Mat &blebsImg, Rect &rectangle, //vector<int> &blebs, int &frameNum) { frame = &img; vector<Point> cir; //***global coordinates of circle*** //cout << "["; for(unsigned int i = 0; i < cir_org.size(); i++){ cir.push_back(Point(cir_org[i].x / scale, cir_org[i].y / scale)); //cout << int(cir_org[i].x / scale) << ", " << int(cir_org[i].y / scale) << "; "; } //cout << "]" << endl; //enlarge the bounding rect by adding a margin (e) to it rect = enlargeRect(boundingRect(Mat(cir)), 5, img.cols, img.rows); //cout << "rect_roi " << boundingRect(Mat(cir)) << "\n"; //cout << "enlarged rect " << rect << endl; dispImg1 = (*frame)(rect).clone(); Mat sub; //*** the rectangle region of ROI (Gray) *** cv::cvtColor(dispImg1, sub, CV_RGB2GRAY); int width = sub.cols; int height = sub.rows; rectangle = rect; // Mat canny; // CannyWithBlur(sub, canny); // imshow("canny", canny); vector<Point> circle_ROI; //***local coordinates of circle*** for (unsigned int i = 0; i < cir.size(); i++){ Point p = Point(cir[i].x - rect.x, cir[i].y - rect.y); circle_ROI.push_back(p); } Mat adapThreshImg1 = Mat::zeros(height, width, sub.type()); //image edge detection for the sub region (roi rect) adaptiveThreshold(sub, adapThreshImg1, 255.0, ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY_INV, blockSize, constValue); //imshow("adapThreshImg1", adapThreshImg1); // dilation and erosion Mat dilerod; dilErod(adapThreshImg1, dilerod, dilSize); //display image 2 -- dilerod of adaptive threshold image GaussianBlur(dilerod, dilerod, Size(3, 3), 2, 2 ); //mask for filtering out the cell of interest Mat mask_conv = Mat::zeros(height, width, CV_8UC1); fillConvexPoly(mask_conv, circle_ROI, Scalar(255)); //imshow("mask_before", mask_conv); //dilate the mask -> region grows Mat mask_conv_dil; Mat element = getStructuringElement( MORPH_ELLIPSE, Size( 2*dilSize+1, 2*dilSize+1 ), Point(dilSize,dilSize) ); dilate(mask_conv, mask_conv_dil, element); //imshow("mask_dil", mask_conv_dil); //bitwise AND on mask and dilerod bitwise_and(mask_conv_dil, dilerod, dispImg2); // findcontours vector<vector<Point> > contours; vector<Vec4i> hierarchy; unsigned int largest_contour_index; dilErodContours(dispImg2, contours, hierarchy, largest_contour_index, perimeter, dispImg1); // find the area of the cell by counting the white area inside the largest contour Mat cellArea = Mat::zeros(height, width, CV_8UC1); drawContours(cellArea, contours, largest_contour_index, Scalar(255), -1, 8, hierarchy, 0, Point() ); //imshow("cellArea", cellArea); area = countNonZero(cellArea); //cout << "frame " << frameNum << "\n"; //cout << contours[largest_contour_index] << endl; //renew circle points as the convex hull vector<Point> convHull; convexHull(contours[largest_contour_index], convHull); // find the centroid of the contour Moments mu = moments(contours[largest_contour_index]); ctroid = Point2f(mu.m10/mu.m00 + rect.x, mu.m01/mu.m00 + rect.y); // find the shape of the cell by the largest contour and centroid shape = findShape(ctroid, contours[largest_contour_index]); ////---- draw largest contour start ---- //draw the largest contour Mat borderImg = Mat::zeros(height, width, CV_8UC1); drawContours(borderImg, contours, largest_contour_index, Scalar(255), 1, 8, hierarchy, 0, Point()); //QString cellFileName0 = "border" + QString::number(frameNum) + ".png"; //imwrite(cellFileName0.toStdString(), borderImg); Mat cell; bitwise_and(cellArea, sub, cell); //cell_alpha = createAlphaMat(cell); // cell image with exactly the contour detected //vector<int> compression_params; //compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION); //compression_params.push_back(9); // QString cellFileName1 = "cell" + QString::number(frameNum) + ".png"; // imwrite(cellFileName1.toStdString(), cell_alpha, compression_params); ////---- draw largest contour end ---- // find the number and the sizes of blebs of the cell Mat smooth; vector<Point> smoothCurve; int WIN = 25; smooth = curveSmooth(borderImg, WIN, contours[largest_contour_index], smoothCurve, convHull); //smooth = curveSmooth(borderImg, WIN, contours[largest_contour_index], smoothCurve, ctroid/*Point(ctroid.x, ctroid.y)*/); //drawPointVectors(dispImg1, smoothCurve, 1, Scalar(159, 120, 28)); Mat smooth_contour; int w = 10; smooth_contour = curveSmooth(borderImg, w, contours[largest_contour_index], smooth_contour_curve, convHull); //smooth_contour = curveSmooth(borderImg, w, contours[largest_contour_index], smooth_contour_curve, ctroid/*Point(ctroid.x, ctroid.y)*/); //imshow("smooth_contour", smooth_contour); for(unsigned int i = 0; i < smooth_contour_curve.size(); i++){ Point p(smooth_contour_curve[i].x + rect.x, smooth_contour_curve[i].y + rect.y); smooth_contour_curve_abs.push_back(p); } // cout << "ctroid X " << ctroid.x << " Y " << ctroid.y << endl; //// for(unsigned int i = 0; i < contours[largest_contour_index].size(); i++) //// cout << "(" << contours[largest_contour_index][i].x + rect.x << ", " << contours[largest_contour_index][i].y + rect.y << ") "; //// cout << endl; // for(unsigned int i = 0; i < smooth_contour_curve_abs.size(); i++) // cout << "(" << smooth_contour_curve_abs[i].x << ", " << smooth_contour_curve_abs[i].y << ") "; // cout << endl; //cout << mask_conv_dil.type() << " " << sub.type() << endl; Mat cell_convex; bitwise_and(smooth_contour, sub, cell_convex); cell_alpha = createAlphaMat(cell_convex); // imshow("cell_convex_contour", cell_alpha); dispImg2 = cell_convex.clone(); //change dispImg2 from gray to rgb for displaying cvtColor(dispImg2, dispImg2, CV_GRAY2RGB); bitwise_not(smooth, smooth); //Mat blebsImg; bitwise_and(smooth, cellArea, blebsImg); // imshow("blebs", blebsImg); // QString cellFileName2 = "blebs" + QString::number(frameNum) + ".png"; // imwrite(cellFileName2.toStdString(), blebs); //QString cellFileName2 = "dispImg1" + QString::number(frameNum) + ".png"; //imwrite(cellFileName2.toStdString(), dispImg1); cir_org.clear(); for(unsigned int i = 0; i < convHull.size(); i++) cir_org.push_back(Point((convHull[i].x + rect.x)*scale, (convHull[i].y + rect.y)*scale)); }
int process(VideoCapture& capture) { long captureTime; cout << "Press q or escape to quit!" << endl; CvFont infoFont; cvInitFont(&infoFont, CV_FONT_HERSHEY_SIMPLEX, 1, 1); namedWindow(VIDEO_WINDOW_NAME, CV_WINDOW_AUTOSIZE); namedWindow(ERODE_PREVIEW_WIN_NAME, CV_WINDOW_NORMAL); resizeWindow(ERODE_PREVIEW_WIN_NAME, 320, 240); ControlsWindow* controlsWindow = new ControlsWindow(); if(fileExists(preferenceFileName)) { loadSettings(controlsWindow, (char*)preferenceFileName); } Mat frame; while (true) { capture >> frame; captureTime = (int)(getTickCount()/getTickFrequency())*1000; if (frame.empty()) break; int target_width = 320; int height = (target_width/capture.get(3 /*width*/)) * capture.get(4 /*height*/); resize(frame, frame, Size(target_width, height)); if (controlsWindow->getBlurDeviation() > 0) { GaussianBlur(frame, frame, Size(GAUSSIAN_KERNEL, GAUSSIAN_KERNEL), controlsWindow->getBlurDeviation()); } //Apply brightness and contrast frame.convertTo(frame, -1, controlsWindow->getContrast(), controlsWindow->getBrightness()); Mat maskedImage = thresholdImage(controlsWindow, frame); Mat erodedImage = erodeDilate(maskedImage, controlsWindow); Mat erodedImageBinary; cvtColor(erodedImage, erodedImageBinary, COLOR_BGR2GRAY); threshold(erodedImageBinary, erodedImageBinary, 0, 255, CV_THRESH_BINARY); if(controlsWindow->getInvert()) { erodedImageBinary = 255 - erodedImageBinary; } cv::SimpleBlobDetector::Params params; params.minDistBetweenBlobs = 50.0f; params.filterByInertia = false; params.filterByConvexity = false; params.filterByColor = true; params.filterByCircularity = false; params.filterByArea = true; params.minArea = 1000.0f; params.maxArea = 100000.0f; params.blobColor = 255; vector<KeyPoint> centers; vector<vector<Point>> contours; ModBlobDetector* blobDetector = new ModBlobDetector(params); vector<vector<Point>> contourHulls; vector<RotatedRect> contourRects; blobDetector->findBlobs(erodedImageBinary, erodedImageBinary, centers, contours); for(vector<Point> ctpts : contours) { vector<Point> hull; convexHull(ctpts, hull); contourHulls.push_back(hull); contourRects.push_back(minAreaRect(hull)); } #ifdef DEBUG_BLOBS drawContours(frame, contours, -1, Scalar(128,255,128), 2, CV_AA); drawContours(frame, contourHulls, -1, Scalar(255, 128,0), 2, CV_AA); int ptnum; for(KeyPoint pt : centers) { Scalar color(255, 0, 255); circle(frame, pt.pt, 5 , color, -1 /*filled*/, CV_AA); circle(frame, pt.pt, pt.size, color, 1, CV_AA); ptnum++; } #endif for(RotatedRect rr : contourRects) { Point2f points[4]; rr.points(points); float side1 = distance(points[0], points[1]); float side2 = distance(points[1], points[2]); float shortestSide = min(side1, side2); float longestSide = max(side1, side2); float aspectRatio = longestSide/shortestSide; int b = 0; bool isTape = objInfo.aspectRatio == 0 ? false : abs(objInfo.aspectRatio - aspectRatio) < 0.2*objInfo.aspectRatio; /* * TODO * Make a list of possible tape candidates * Use tape candidate with smallest difference in ratio to the real ratio as the tape */ if(isTape) { b = 255; string widthText = "Width (px): "; widthText.append(toString(longestSide)); string heightText = "Height (px): "; heightText.append(toString(shortestSide)); string rotText = "Rotation (deg): "; rotText.append(toString(abs((int)rr.angle))); string distText; if(camSettings.focalLength == -1) { distText = "Focal length not defined"; } else { float dist = objInfo.width * camSettings.focalLength / longestSide; distText = "Distance (cm): "; distText.append(toString(dist)); } putText(frame, widthText, Point(0, 20), CV_FONT_HERSHEY_SIMPLEX, 0.5f, Scalar(0, 255, 255)); putText(frame, heightText, Point(0, 40), CV_FONT_HERSHEY_SIMPLEX, 0.5f, Scalar(0, 255, 255)); putText(frame, rotText, Point(0, 60), CV_FONT_HERSHEY_SIMPLEX, 0.5f, Scalar(0, 255, 255)); putText(frame, distText, Point(0, 80), CV_FONT_HERSHEY_SIMPLEX, 0.5f, Scalar(0, 255, 255)); } rotated_rect(frame, rr, Scalar(b, 0, 255)); if(isTape)break; } if(objInfo.aspectRatio == 0) { putText(frame, "Invalid object info (object.xml)", Point(0, 20), CV_FONT_HERSHEY_SIMPLEX, 0.5f, Scalar(0, 255, 255)); } delete blobDetector; imshow(ERODE_PREVIEW_WIN_NAME, erodedImageBinary); imshow(VIDEO_WINDOW_NAME, frame); //int waitTime = max((int)(((1.0/framerate)*1000) // - ((int)(getTickCount()/getTickFrequency())*1000 - captureTime)) // , 1); char key = (char)waitKey(1); switch (key) { case 'q': case 'Q': case 27: //escape saveSettings(controlsWindow, (char*)preferenceFileName); return 0; default: break; } std::this_thread::yield(); } saveSettings(controlsWindow, (char*)preferenceFileName); delete(controlsWindow); destroyAllWindows(); return 0; }
int main(int argc,char**argv) { int scale = 1; int delta = 0; int ddepth = CV_16S; // check the number of parameter if(argc !=2) { printf("please follow like this\n"); printf("exe[] img_name\n"); return -1; } // reads image img_src = imread(argv[1]); // check whether read operation is ok or not if(img_src.data == NULL) { printf("could not open or find the image!\n"); return -1; } // use Gaussian blur to reduce the noise GaussianBlur(img_src,img_src,Size(3,3),0,0,BORDER_DEFAULT); // convert source image to gray image cvtColor(img_src,img_gray,CV_BGR2GRAY); // sobel in x direction Sobel(img_gray,grad_x,ddepth,1,0,3,scale,delta,BORDER_DEFAULT); convertScaleAbs(grad_x,abs_grad_x); // use sobel in y direction Sobel(img_gray,grad_y,ddepth,0,1,3,scale,delta,BORDER_DEFAULT); convertScaleAbs(grad_y,abs_grad_y); // add weight,and addWeighted(abs_grad_x,0.5,abs_grad_y,0.5,0,grad); // use threshold to binarition and threshold select use the OTSU method threshold(grad,img_bin_thre,0,255,THRESH_BINARY|THRESH_OTSU); // first Dilate,second erode Mat element = getStructuringElement(MORPH_RECT,Size(2*1+1,2*1+1),Point(-1,-1)); for(int i = 0;i < 3; i++) { morphologyEx(img_bin_thre,img_bin_thre,MORPH_OPEN,element); morphologyEx(img_bin_thre,img_bin_thre,MORPH_CLOSE,element); } // origin method ,this is worse than morphologyEx // dilate(img_bin_thre,img_bin_thre,element); // namedWindow("dilated",CV_WINDOW_NORMAL); // imshow("dilated",img_bin_thre); // erode(img_bin_thre,img_bin_thre,element); // namedWindow("erode",CV_WINDOW_NORMAL); // imshow("erode",img_bin_thre); // find contour,in here must use the binarition image // define vector<Vec4i> hierarchy; vector< vector<Point> >contours; // use function findContours(img_bin_thre,contours,hierarchy,CV_RETR_CCOMP,CV_CHAIN_APPROX_SIMPLE,Point(0,0)); // please change min and the max area value based on reality int min_area = 100000; int max_area = 300000; Rect mRect; int tempArea; // define the color drawing contour Scalar color = Scalar(255,255,0); Mat drawing = Mat::zeros(img_bin_thre.size(),CV_8UC1); for(int i = 0;i < contours.size();i++) { // get the minimum rectangle of the contours mRect = boundingRect(contours[i]); // computer the square of mRect tempArea = mRect.height * mRect.width; // for debug // printf("tempArea.height:%d\ttempArea.width:%d\ttempArea.area=%d\n",mRect.height,mRect.width,tempArea); // filter area which meet the requirement if(((double)mRect.width/(double)mRect.height) > 2.0 && (tempArea > min_area) && ((double)mRect.width/(double)mRect.height < 4) && (tempArea < max_area)) // draw contours { drawContours(drawing,contours,i,color,2,8,hierarchy); // here use 2 image ,one is just from image which be processed by threshold,the other is the original gray image,if you just use first,you // may not getRectSubPix(img_bin_thre,Size(mRect.width,mRect.height),Point(mRect.x+mRect.width/2,mRect.y\ +mRect.height/2),img_get_rect); getRectSubPix(img_gray,Size(mRect.width,mRect.height),Point(mRect.x+mRect.width/2,mRect.y\ +mRect.height/2),img_get_rect_new); } } if(img_get_rect.data == NULL) { printf("img_get rect is null\n"); return -1; } if(img_get_rect_new.data == NULL) { printf("img_get_rect_new is null!\n"); return -1; } // use the HoughLinesP // define lines vector<Vec4i> lines; // Mat color_dst; // img_lines = img_get_rect.clone(); cvtColor(img_get_rect,img_lines,CV_GRAY2BGR); // check the line in image img_get_rect HoughLinesP(img_get_rect,lines,1,CV_PI/180,200,200,10); printf("lines.size()=%d\n",lines.size()); int distance = 0; // int theta; double temp_slope = 0,slope; int res_x1,res_y1,res_x2,res_y2; // define map vector for computer the line used frequency // vector <int,int> ivect;//first is the number of this line , next is the longest distance // map <double,ivect> imap; int delta_x,delta_y; std::vector <dou_int> ivec; std::vector <dou_int>::iterator iter; for(size_t i = 0;i < lines.size();i++) { Vec4i l = lines[i]; line(img_lines,Point(l[0],l[1]),Point(l[2],l[3]),Scalar(0,0,255),3); // find tilt angle if(l[2]-l[0] == 0) ; else { // computer this line 's slope // delta_x / delta_y delta_y = (l[3]-l[1]); delta_x = (l[2]-l[0]); distance = delta_y*delta_y+delta_x*delta_x; temp_slope = ((double)delta_y)/((double)(delta_x)); printf("in i=%d,delta_y=%d,delta_x=%d\n",i,delta_y,delta_x); for(iter = ivec.begin();iter != ivec.end();iter++) { // if in one line,num++,update the max length if(abs(iter->slope - temp_slope) < (double)0.01) { iter->num++; if(iter->maxlength < distance) { iter->maxlength = distance; iter->v0 = Point(l[0],l[1]); iter->v1 = Point(l[2],l[3]); } break; } } // not find this slope ,must add it by hand if(iter == ivec.end()) { ivec.push_back(dou_int(temp_slope,distance,1,Point(l[0],l[1]),Point(l[2],l[3]))); } } } int max = 0; int j = 0; int index = 0; dou_int res; for(j=0,iter = ivec.begin();iter != ivec.end();j++,iter++) { if(iter->num > max) { max = iter->num; index = j; } } printf("index is %d\n",index); for(j=0,iter = ivec.begin();iter != ivec.end() && j <= index;j++,iter++) { if(j == index) { res = dou_int(iter->slope,iter->maxlength,iter->num,iter->v0,iter->v1); printf("slope is %f\n",iter->slope); break; } } // drawing the tilt line line(img_lines,res.v0,res.v1,Scalar(255,255,0),1); Mat img_lines_out; Point center = Point(img_lines.cols/2,img_lines.rows/2); double angle =(double)(180/CV_PI)*(double)atan(res.slope); printf("angle is :%f\n",angle); Mat rot_mat = getRotationMatrix2D(center,angle,1.0); warpAffine(img_lines,img_lines_out,rot_mat,img_lines.size()); Mat img_rect; warpAffine(img_get_rect_new,img_rect,rot_mat,img_get_rect_new.size()); cvtColor(img_lines_out,img_lines_out,CV_BGR2GRAY); printf("img_clip's channel is:%d\n",img_lines_out.channels()); threshold(img_lines_out,img_lines_out,10,255,THRESH_BINARY | THRESH_OTSU); Mat img_clip; int up,down; if(-1 != remove_Border_Vertical(img_lines_out,up,down)) { printf("up=%d,down=%d\n",up,down); getRectSubPix(img_lines_out,Size(img_lines_out.cols,down-up),Point(img_lines_out.cols/2,up+(down-up)/2),img_clip); namedWindow("line_clip",CV_WINDOW_NORMAL); imshow("line_clip",img_clip); getRectSubPix(img_rect,Size(img_rect.cols,down-up),Point(img_rect.cols/2,up+(down-up)/2),img_clip); namedWindow("new_clip",CV_WINDOW_NORMAL); imshow("new_clip",img_clip); } // binarition OTSU threshold(img_clip,img_clip,10,255,THRESH_BINARY | THRESH_OTSU); namedWindow("newrect",CV_WINDOW_NORMAL); imshow("newrect",img_clip); parting_char(img_clip); waitKey(0); return 0; }
//-------------------------------------------------------------- void scan(Cam *cam, ofImage *grislaser, ofImage *TaL, ofImage *TsL){ Mat image1; Mat Laser1; Mat Tot, gris, grisc; Mat HSV; Mat threshold1; // camera(cam); int valueRL = 60; int valueGL = 0; int valueBL = 0; Mat tt1, tt2, tt3, colo; Mat matImg; cv::Point punt; tt1 = toCv(*TaL).clone(); Laser1 = tt1.clone(); tt2 = toCv(*TsL).clone(); Tot = tt2.clone(); Mat th1, th2; Mat image2; absdiff(Laser1, Tot, image1); cvtColor(image1, HSV, CV_BGR2HSV); inRange(HSV, Scalar(cam->Bi, cam->Gi, cam->Ri), Scalar(cam->Bs, cam->Gs, cam->Rs), threshold1); th1 = threshold1.clone(); image2 = image1.clone(); GaussianBlur(threshold1, th1, cv::Size(1,1), 0,0); GaussianBlur(image2, image1, cv::Size(cam->blur_ksizew, cam->blur_ksizeh), cam->blur_sigmax, cam->blur_sigmay); cam_cap_subpixel(cam, image1, threshold1); cvtColor(image1, gris, CV_BGR2GRAY); cvtColor(gris, grisc, CV_GRAY2BGR); for(int i=0; i<cam->resy; i++){ cv::Point paux1; paux1.x = (int)cam->p[i].x; paux1.y = (int)cam->p[i].y; line(grisc, paux1, paux1, Scalar(255,0,0), 1,8,0); } ofImage gl,L1,Tt; toOf(grisc, gl); gl.update(); *grislaser = gl; toOf(Laser1, L1); L1.update(); *TaL = L1; toOf(Tot, Tt); Tt.update(); *TsL = Tt; }
/* * Segment an image * * Returns a color image representing the segmentation. * * Input: * im: image to segment. * sigma: to smooth the image. * c: constant for threshold function. * min_size: minimum component size (enforced by post-processing stage). * nu_ccs: number of connected components in the segmentation. * Output: * colors: colors assigned to each components * pImgInd: index of each components, [0, colors.size() -1] */ int SegmentImage(CMat &_src3f, Mat &pImgInd, double sigma, double c, int min_size) { CV_Assert(_src3f.type() == CV_32FC3); int width(_src3f.cols), height(_src3f.rows); Mat smImg3f; GaussianBlur(_src3f, smImg3f, Size(), sigma, 0, BORDER_REPLICATE); // build graph edge *edges = new edge[width*height*4]; int num = 0; { for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { if (x < width-1) { edges[num].a = y * width + x; edges[num].b = y * width + (x+1); edges[num].w = diff(smImg3f, x, y, x+1, y); num++; } if (y < height-1) { edges[num].a = y * width + x; edges[num].b = (y+1) * width + x; edges[num].w = diff(smImg3f, x, y, x, y+1); num++; } if ((x < width-1) && (y < height-1)) { edges[num].a = y * width + x; edges[num].b = (y+1) * width + (x+1); edges[num].w = diff(smImg3f, x, y, x+1, y+1); num++; } if ((x < width-1) && (y > 0)) { edges[num].a = y * width + x; edges[num].b = (y-1) * width + (x+1); edges[num].w = diff(smImg3f, x, y, x+1, y-1); num++; } } } } // segment universe *u = segment_graph(width*height, num, edges, (float)c); // post process small components for (int i = 0; i < num; i++) { int a = u->find(edges[i].a); int b = u->find(edges[i].b); if ((a != b) && ((u->size(a) < min_size) || (u->size(b) < min_size))) u->join(a, b); } delete [] edges; // pick random colors for each component map<int, int> marker; pImgInd.create(smImg3f.size(), CV_32S); int idxNum = 0; for (int y = 0; y < height; y++) { int *imgIdx = pImgInd.ptr<int>(y); for (int x = 0; x < width; x++) { int comp = u->find(y * width + x); if (marker.find(comp) == marker.end()) marker[comp] = idxNum++; int idx = marker[comp]; imgIdx[x] = idx; } } delete u; return idxNum; }
// LED detector void LEDDetector::findLeds(const cv::Mat &image, cv::Rect ROI, const int &threshold_value, const double &gaussian_sigma, const double &min_blob_area, const double &max_blob_area, const double &max_width_height_distortion, const double &max_circular_distortion, List2DPoints &pixel_positions, std::vector<cv::Point2f> &distorted_detection_centers, const cv::Mat &camera_matrix_K, const std::vector<double> &camera_distortion_coeffs, const cv::Mat &camera_matrix_P) { // Threshold the image cv::Mat bw_image; //cv::threshold(image, bwImage, threshold_value, 255, cv::THRESH_BINARY); cv::threshold(image(ROI), bw_image, threshold_value, 255, cv::THRESH_TOZERO); // Gaussian blur the image cv::Mat gaussian_image; cv::Size ksize; // Gaussian kernel size. If equal to zero, then the kerenl size is computed from the sigma ksize.width = 0; ksize.height = 0; GaussianBlur(bw_image.clone(), gaussian_image, ksize, gaussian_sigma, gaussian_sigma, cv::BORDER_DEFAULT); //cv::imshow( "Gaussian", gaussian_image ); // Find all contours std::vector<std::vector<cv::Point> > contours; cv::findContours(gaussian_image.clone(), contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); unsigned numPoints = 0; // Counter for the number of detected LEDs // Vector for containing the detected points that will be undistorted later std::vector<cv::Point2f> distorted_points; // Identify the blobs in the image for (unsigned i = 0; i < contours.size(); i++) { double area = cv::contourArea(contours[i]); // Blob area cv::Rect rect = cv::boundingRect(contours[i]); // Bounding box double radius = (rect.width + rect.height) / 4; // Average radius cv::Moments mu; mu = cv::moments(contours[i], false); cv::Point2f mc; mc = cv::Point2f(mu.m10 / mu.m00, mu.m01 / mu.m00) + cv::Point2f(ROI.x, ROI.y); // Look for round shaped blobs of the correct size if (area >= min_blob_area && area <= max_blob_area && std::abs(1 - std::min((double)rect.width / (double)rect.height, (double)rect.height / (double)rect.width)) <= max_width_height_distortion && std::abs(1 - (area / (CV_PI * std::pow(rect.width / 2, 2)))) <= max_circular_distortion && std::abs(1 - (area / (CV_PI * std::pow(rect.height / 2, 2)))) <= max_circular_distortion) { distorted_points.push_back(mc); numPoints++; } } // These will be used for the visualization distorted_detection_centers = distorted_points; if (numPoints > 0) { // Vector that will contain the undistorted points std::vector<cv::Point2f> undistorted_points; // Undistort the points cv::undistortPoints(distorted_points, undistorted_points, camera_matrix_K, camera_distortion_coeffs, cv::noArray(), camera_matrix_P); // Resize the vector to hold all the possible LED points pixel_positions.resize(numPoints); // Populate the output vector of points for (unsigned j = 0; j < numPoints; ++j) { Eigen::Vector2d point; point(0) = undistorted_points[j].x; point(1) = undistorted_points[j].y; pixel_positions(j) = point; } } }
bool ForegroundExtractorNew::compute(Mat& image_in, Mat& image_smoothed_in, MotionProcessorNew& motion_processor, const string name, const bool visualize) { if (mode == "tool") { threshold(image_in, image_foreground, max(motion_processor.gray_threshold_left, motion_processor.gray_threshold_right), 254, THRESH_BINARY); blob_detector.compute(image_foreground, 254, 0, WIDTH_SMALL, 0, HEIGHT_SMALL, false); if (visualize && enable_imshow) imshow("image_foreground" + name, image_foreground); return true; } const int x_separator_middle_median = motion_processor.x_separator_middle_median; const uchar gray_threshold_left = motion_processor.gray_threshold_left; const uchar gray_threshold_right = motion_processor.gray_threshold_right; const uchar diff_threshold = motion_processor.diff_threshold; Mat image_foreground_smoothed = Mat::zeros(HEIGHT_SMALL, WIDTH_SMALL, CV_8UC1); for (int i = 0; i < WIDTH_SMALL; ++i) for (int j = 0; j < HEIGHT_SMALL; ++j) { const uchar gray_current = image_smoothed_in.ptr<uchar>(j, i)[0]; if ((i <= x_separator_middle_median && gray_current > gray_threshold_left) || (i > x_separator_middle_median && gray_current > gray_threshold_right)) { if (motion_processor.image_background_static.ptr<uchar>(j, i)[0] == 255) image_foreground_smoothed.ptr<uchar>(j, i)[0] = 254; else image_foreground_smoothed.ptr<uchar>(j, i)[0] = abs(gray_current - motion_processor.image_background_static.ptr<uchar>(j, i)[0]); } } threshold(image_foreground_smoothed, image_foreground_smoothed, diff_threshold, 254, THRESH_BINARY); GaussianBlur(image_foreground_smoothed, image_foreground_smoothed, Size(1, 9), 0, 0); threshold(image_foreground_smoothed, image_foreground_smoothed, 100, 254, THRESH_BINARY); Mat image_foreground_regular = Mat::zeros(HEIGHT_SMALL, WIDTH_SMALL, CV_8UC1); for (int i = 0; i < WIDTH_SMALL; ++i) for (int j = 0; j < HEIGHT_SMALL; ++j) { const uchar gray_current = image_in.ptr<uchar>(j, i)[0]; if ((i <= x_separator_middle_median && gray_current > gray_threshold_left) || (i > x_separator_middle_median && gray_current > gray_threshold_right)) { if (motion_processor.image_background_static.ptr<uchar>(j, i)[0] == 255) image_foreground_regular.ptr<uchar>(j, i)[0] = 254; else image_foreground_regular.ptr<uchar>(j, i)[0] = abs(gray_current - motion_processor.image_background_static.ptr<uchar>(j, i)[0]); } } threshold(image_foreground_regular, image_foreground_regular, diff_threshold, 254, THRESH_BINARY); image_foreground = Mat::zeros(HEIGHT_SMALL, WIDTH_SMALL, CV_8UC1); for (int i = 0; i < WIDTH_SMALL; ++i) for (int j = 0; j < HEIGHT_SMALL; ++j) if (image_foreground_smoothed.ptr<uchar>(j, i)[0] > 0 && image_foreground_regular.ptr<uchar>(j, i)[0] > 0) image_foreground.ptr<uchar>(j, i)[0] = 254; blob_detector.compute(image_foreground, 254, 0, WIDTH_SMALL, 0, HEIGHT_SMALL, false); for (BlobNew& blob : *blob_detector.blobs) if (blob.count < motion_processor.noise_size || (blob.width <= 3 || blob.height <= 3) || blob.y > motion_processor.y_separator_motion_down_median || blob.x_max < motion_processor.x_separator_motion_left_median || blob.x_min > motion_processor.x_separator_motion_right_median) { blob.active = false; blob.fill(image_foreground, 0); } if (visualize && enable_imshow) imshow("image_foreground" + name, image_foreground); return true; }
std::vector<cv::Mat>* laneTracker::roadColorDetect() { //Rect(x, y ,width, height) //Rect roi(0, src_.rows/2, src_.cols, src_.rows/2); //TODO dynamicly adjust road_rect cv::Mat roadRegion = src_(ROAD_RECT(src_.cols, src_.rows)); cv::Mat ycrcb; cvtColor(roadRegion, ycrcb, CV_BGR2YCrCb); /// Separate the image in 3 places ( B, G and R ) std::vector<cv::Mat> bgr_planes; split(roadRegion, bgr_planes); std::vector<cv::Mat> ycbcr_planes; split(ycrcb, ycbcr_planes); /// Establish the number of bins, x-axis int histSize = 256; /// Set the ranges ( for B,G,R) ) float range[] = { 0, 256 } ; const float* histRange = { range }; bool uniform = true; bool accumulate = false; cv::Mat b_hist, g_hist, r_hist; cv::Mat b_blur, g_blur, r_blur; cv::Mat y_hist, cr_hist, cb_hist; cv::Mat y_blur, cr_blur, cb_blur; GaussianBlur(bgr_planes[0], b_blur, cv::Size(5,5), 0, 0); GaussianBlur(bgr_planes[1], g_blur, cv::Size(5,5), 0, 0); GaussianBlur(bgr_planes[2], r_blur, cv::Size(5,5), 0, 0); GaussianBlur(ycbcr_planes[0], y_blur, cv::Size(5,5), 0, 0); GaussianBlur(ycbcr_planes[1], cr_blur, cv::Size(5,5), 0, 0); GaussianBlur(ycbcr_planes[2], cb_blur, cv::Size(5,5), 0, 0); /// Compute the histograms: calcHist( &b_blur, 1, 0, cv::Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate ); calcHist( &g_blur, 1, 0, cv::Mat(), g_hist, 1, &histSize, &histRange, uniform, accumulate ); calcHist( &r_blur, 1, 0, cv::Mat(), r_hist, 1, &histSize, &histRange, uniform, accumulate ); calcHist( &y_blur, 1, 0, cv::Mat(), y_hist, 1, &histSize, &histRange, uniform, accumulate ); calcHist( &cr_blur, 1, 0, cv::Mat(), cr_hist, 1, &histSize, &histRange, uniform, accumulate ); calcHist( &cb_blur, 1, 0, cv::Mat(), cb_hist, 1, &histSize, &histRange, uniform, accumulate ); /// Normalize the result to [ 0, 100 ], percentage representation,, y-axis // for example, there are N blue pixels at 150 [0, 255], and N is the max // from [0, 255], then N is max of the range:100 normalize(b_hist, b_hist, 0, 100, cv::NORM_MINMAX, -1, cv::Mat() ); normalize(g_hist, g_hist, 0, 100, cv::NORM_MINMAX, -1, cv::Mat() ); normalize(r_hist, r_hist, 0, 100, cv::NORM_MINMAX, -1, cv::Mat() ); normalize(y_hist, y_hist, 0, 100, cv::NORM_MINMAX, -1, cv::Mat() ); normalize(cr_hist, cr_hist, 0, 100, cv::NORM_MINMAX, -1, cv::Mat() ); normalize(cb_hist, cb_hist, 0, 100, cv::NORM_MINMAX, -1, cv::Mat() ); // clear vector first pHistVector_->clear(); pHistVector_->push_back(cr_hist); pHistVector_->push_back(cb_hist); return pHistVector_; }
void *sobel_loop(void *number) { /* if(set_single_core_affinity()!=EXIT_SUCCESS) { perror("Core Affinity"); } */ int i=0; Mat sobel_src, src_gray, s_src; Mat grad; struct thread_limits *ptr_obj = (struct thread_limits *) number; int start_loop = ptr_obj->start_no; int stop_loop = ptr_obj->stop_no; for (i=start_loop; i<=stop_loop; i++) { /*------------------------- Loading the Image --------------------------*/ // Select the right frame sprintf(frame_name,"Frame_no_%05u.ppm",i); // Load the Image sobel_src = imread( frame_name,1 ); if( !sobel_src.data ) { perror("Reading from file"); } // Apply Gaussian Blur function GaussianBlur( sobel_src, s_src, Size(3,3), 0, 0, BORDER_DEFAULT ); // Convert Color image to gray //printf("cvtcolor\n"); cvtColor( s_src, src_gray, CV_RGB2GRAY ); //printf("after cvtcolor\n"); // Generate x and y matrix Mat sobel_x, sobel_y; Mat sobel_abs_x, sobel_abs_y; // Gradient X Sobel( src_gray, sobel_x, SOBEL_DEPTH, 1, 0, 3, SOBEL_SCALE, SOBEL_DELTA, BORDER_DEFAULT ); convertScaleAbs( sobel_x, sobel_abs_x ); // Gradient Y Sobel( src_gray, sobel_y, SOBEL_DEPTH, 0, 1, 3, SOBEL_SCALE, SOBEL_DELTA, BORDER_DEFAULT ); convertScaleAbs( sobel_y, sobel_abs_y ); // Total Gradient addWeighted( sobel_abs_x, 0.5, sobel_abs_y, 0.5, 0, grad ); /*------------------------- Storing the Image ---------------------------*/ // Storing the Image sprintf(frame_name2,"Sobel_frame_no_%05u.ppm",i); imwrite(frame_name2, grad); } // End of 'for' loop return (NULL); }
Result CalSpermCount::calNum(Mat img) { Mat tmp, tmp_back; // int col = 800, row = 600; Size dsize = Size(nshowcol, nshowrow); Mat image2show = Mat(dsize,CV_8U); GaussianBlur(img,img,cv::Size(5,5), 1.5); if(nShowMidRst) ShowImage("after filtering", img); //cvSmooth(img, img, CV_MEDIAN, 3, 0, 0, 0); //中值滤波,消除小的噪声; //Mat element(9,9,CV_8U,Scalar(1)); Mat element = getStructuringElement(MORPH_RECT,Size(10,10)); erode(img, tmp,element); //ShowImage("erode",tmp); dilate(tmp,tmp_back,element); ::resize(tmp_back, image2show,dsize); //cvNamedWindow("dilate"); //imshow("dilate", image2show); //ShowImage("dilate",tmp_back); morphologyEx(img,dst_gray,MORPH_TOPHAT,element); //morphologyEx(img,dst_gray,MORPH_BLACKHAT,cv::Mat()); //dst_gray = img; //绘制直方图 Histgram1D hist; hist.stretch(dst_gray,0.01f); if(nShowMidRst) ShowImage("Histogram", hist.getHistogramImage(dst_gray, 1)); Mat tmpImage; //::equalizeHist(dst_gray,tmpImage); //ShowImage("拉伸后", tmpImage); //ShowImage("拉伸后Histogram", hist.getHistogramImage(tmpImage, 1)); if(nShowMidRst) { ShowImage("Picture EQ", hist.stretch(dst_gray, 50)); ShowImage("after draw, Histogram", hist.getHistogramImage(hist.stretch(dst_gray,50), 1)); } dst_gray = hist.stretch(dst_gray, 50); //dst_gray = ::equalizeHist(dst_gray,dst_gray); //dst_gray = tmp_back - img ; //dst_gray = img ; ::resize(dst_gray, image2show,dsize); #if 0 // No GUI if(nShowMidRst) cvNamedWindow(WINDOWNAME); ::createTrackbar("filter pattern",WINDOWNAME,&g_nThresholdType,4,on_Theshold); createTrackbar("theshold value",WINDOWNAME,&g_nThresholdValue,255,on_Theshold); #endif //初始化自定义回调函数 on_Theshold(0,0); //adaptiveThreshold(dst_gray,dstimgbw,255,adaptive_method,CV_THRESH_BINARY,blocksize,0); //cvAdaptiveThreshold(img, dst_bw,255,adaptive_method,//自适应阀值,blocksize为奇数 // CV_THRESH_BINARY,blocksize,offset); // ::resize(dstimgbw, image2show,dsize); // cvNamedWindow("src2"); // imshow("src2", image2show); // waitKey(0); vector<vector<Point> > contours; findContours(dstimgbw,contours,CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); Mat rst(img.size(),CV_8U,Scalar(0)); drawContours(rst,contours,-1,255,1); int cmin = minArea; int cmax = maxArea; vector<vector<Point> >::iterator itc = contours.begin(); int i = 0; result.LittleNum = 0; result.AimNum = 0; result.LargeNum = 0; fallcount = contours.size(); while(itc!=contours.end()) { if(itc->size() < cmin ) { result.LittleNum ++; itc = contours.erase(itc); //i++; } else if(itc->size() > cmax) { itc = contours.erase(itc); result.LargeNum ++; } else { result.AimNum ++; cout <<i<<" = "<< itc->size()<<endl; i++; ++itc; } } Mat rst2(img.size(),CV_8UC3,Scalar(0,0,0)); drawContours(rst2,contours,-1,cv::Scalar(255,255,255),1); char sz1[MAX_PATH],sz2[MAX_PATH],sz3[MAX_PATH]; char sz4[MAX_PATH]; char szError[MAX_PATH] = " "; fcount = fratio * result.AimNum; if(result.LittleNum/fallcount > fminRatio || result.LargeNum/fallcount > fmaxRatio) sprintf(szError,"Sample is dirty"); sprintf(sz1,"Aim Num = %d", result.AimNum); sprintf(sz2,"Little Num=%d", result.LittleNum); sprintf(sz3,"Large Num=%d", result.LargeNum); sprintf(sz4,"Count =%3.3f", fcount); putText(rst2,sz1,cv::Point(10,10),cv::FONT_HERSHEY_PLAIN, 1.0, cv::Scalar(255,0,0), 2); putText(rst2,sz2,cv::Point(10,30),cv::FONT_HERSHEY_PLAIN, 1.0, cv::Scalar(255,0,0), 2); putText(rst2,sz3,cv::Point(10,50),cv::FONT_HERSHEY_PLAIN, 1.0, cv::Scalar(255,0,0), 2); putText(rst2,sz4,cv::Point(10,70),cv::FONT_HERSHEY_PLAIN, 1.0, cv::Scalar(255,0,255), 2); putText(rst2,szError,cv::Point(10,90),cv::FONT_HERSHEY_PLAIN, 1.0, cv::Scalar(0,0,255), 2); cout << "Aim Num = "<<result.AimNum<<endl; cout << "Little Num = "<<result.LittleNum<<endl; cout << "Large Num = "<<result.LargeNum<<endl; cout << "Count = "<<fcount<<endl; cout << "all = "<<contours.size()<<endl; ShowImage("result",rst2); //waitKey(0); return result; }
void imgproc(const uint8_t *image, int width, int height) { cv::Mat img(height, width, CV_8UC1, const_cast<uint8_t*>(image), width); imshow("Original", img); cv::waitKey(1); return; cv::Mat src = img.clone(); cv::Mat color_src(height, width, CV_8UC3); cvtColor(src, color_src, CV_GRAY2RGB); // Image processing starts here GaussianBlur(src, src, cv::Size(3,3), 0); adaptiveThreshold(src, src, 255, cv::ADAPTIVE_THRESH_GAUSSIAN_C, cv::THRESH_BINARY_INV, 5, 3); //equalizeHist(src, src); // TODO: Can think about using multiple thresholds and choosing one where // we can detect a pattern //threshold(src, src, 100, 255, cv::THRESH_BINARY_INV); imshow("Thresholded", src); std::vector<std::vector<cv::Point> > contours; findContours(src, contours, CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE); //printf("Num contours: %lu\n", contours.size()); std::vector<double> contour_area, contour_arclength; contour_area.resize(contours.size()); contour_arclength.resize(contours.size()); std::vector<unsigned int> circle_index; for(unsigned int idx = 0; idx < contours.size(); idx++) { if(contours[idx].size() > 25) { cv::Mat contour(contours[idx]); contour_area[idx] = contourArea(contour); if(contour_area[idx] > 50) { contour_arclength[idx] = arcLength(contour,true); float q = 4*M_PI*contour_area[idx] / (contour_arclength[idx]*contour_arclength[idx]); if(q > 0.8f) { circle_index.push_back(idx); //printf("isoperimetric quotient: %f\n", q); //Scalar color( rand()&255, rand()&255, rand()&255 ); //drawContours(contours_dark, contours, idx, color, 1, 8); } } } } std::list<Circle> circles; for(unsigned int i = 0; i < circle_index.size(); i++) { Circle c; cv::Moments moment = moments(contours[circle_index[i]]); float inv_m00 = 1./moment.m00; c.center = cv::Point2f(moment.m10*inv_m00, moment.m01*inv_m00); c.radius = (sqrtf(contour_area[circle_index[i]]/M_PI) + contour_arclength[circle_index[i]]/(2*M_PI))/2.0f; circles.push_back(c); } // Get the circles with centers close to each other std::vector<std::list<Circle> > filtered_circles; std::list<Circle>::iterator it = circles.begin(); unsigned int max_length = 0; while(it != circles.end()) { std::list<Circle> c; c.push_back(*it); cv::Point c1 = it->center; std::list<Circle>::iterator it2 = it; it2++; while(it2 != circles.end()) { cv::Point c2 = it2->center; std::list<Circle>::iterator it3 = it2; it2++; if(hypotf(c2.x - c1.x, c2.y - c1.y) < 10) { c.push_back(*it3); circles.erase(it3); } } unsigned int length_c = c.size(); if(length_c > 1 && length_c > max_length) { max_length = length_c; filtered_circles.push_back(c); } it2 = it; it++; circles.erase(it2); } if(filtered_circles.size() > 0) { Circle target_circle; target_circle.radius = std::numeric_limits<float>::max(); for(it = filtered_circles.back().begin(); it != filtered_circles.back().end(); it++) { //printf("circle: c: %f, %f, r: %f\n", it->center.x, it->center.y, it->radius); if(it->radius < target_circle.radius) { target_circle.radius = it->radius; target_circle.center = it->center; } } circle(color_src, cv::Point(target_circle.center.x, target_circle.center.y), target_circle.radius, cv::Scalar(0,0,255), 2); printf("target: c: %f, %f, r: %f\n", target_circle.center.x, target_circle.center.y, target_circle.radius); } #if defined(CAPTURE_VIDEO) static cv::VideoWriter video_writer("output.mp4", CV_FOURCC('M','J','P','G'), 20, cv::Size(width, height)); video_writer.write(color_src); #endif imshow("Target", color_src); cv::waitKey(1); }
void StereoVar::operator ()( const Mat& left, const Mat& right, Mat& disp ) { CV_Assert(left.size() == right.size() && left.type() == right.type()); CvSize imgSize = left.size(); int MaxD = MAX(labs(minDisp), labs(maxDisp)); int SignD = 1; if (MIN(minDisp, maxDisp) < 0) SignD = -1; if (minDisp >= maxDisp) {MaxD = 256; SignD = 1;} Mat u; if ((flags & USE_INITIAL_DISPARITY) && (!disp.empty())) { CV_Assert(disp.size() == left.size() && disp.type() == CV_8UC1); disp.convertTo(u, CV_32FC1, static_cast<double>(SignD * MaxD) / 256); } else { u.create(imgSize, CV_32FC1); u.setTo(0); } // Preprocessing Mat leftgray, rightgray; if (left.type() != CV_8UC1) { cvtColor(left, leftgray, CV_BGR2GRAY); cvtColor(right, rightgray, CV_BGR2GRAY); } else { left.copyTo(leftgray); right.copyTo(rightgray); } if (flags & USE_EQUALIZE_HIST) { equalizeHist(leftgray, leftgray); equalizeHist(rightgray, rightgray); } if (poly_sigma > 0.0001) { GaussianBlur(leftgray, leftgray, cvSize(poly_n, poly_n), poly_sigma); GaussianBlur(rightgray, rightgray, cvSize(poly_n, poly_n), poly_sigma); } if (flags & USE_AUTO_PARAMS) { penalization = PENALIZATION_TICHONOV; autoParams(); } Mat I1, I2; leftgray.convertTo(I1, CV_32FC1); rightgray.convertTo(I2, CV_32FC1); leftgray.release(); rightgray.release(); Mat I2x = diffX(I2); FMG(I1, I2, I2x, u, levels - 1); I1.release(); I2.release(); I2x.release(); disp.create( left.size(), CV_8UC1 ); u = abs(u); u.convertTo(disp, disp.type(), 256 / MaxD, 0); u.release(); }
int showImages (unsigned char *data, int n, int m, int nt) { Mat img_max_gauss, img_gauss_max, img_max_bm3d, img_max; Mat imgc_max_gauss, imgc_gauss_max, imgc_max_bm3d, imgc_max; Mat img_max_gauss_canny, img_gauss_max_canny, img_max_bm3d_canny, img_max_canny; Mat imgc_max_gauss_canny, imgc_gauss_max_canny, imgc_max_bm3d_canny, imgc_max_canny; Mat img_max_gauss_watershed, img_gauss_max_watershed, img_max_bm3d_watershed, img_max_watershed; img_max.create (n, m, CV_8UC1); img_max.setTo (0); img_gauss_max.create (n, m, CV_8UC1); img_gauss_max.setTo (0); for (int i = 0; i < nt; i++) { /*Mat img (n, m, imgtype, data + i * n * m), grayImg; img = min (img, 400); double minVal, maxVal; minMaxLoc (img, &minVal, &maxVal); //find minimum and maximum intensities img.convertTo (img, CV_8U, 255.0 / (maxVal - minVal), -minVal * 255.0 / (maxVal - minVal)); img_max = max (img, img_max); GaussianBlur (img, img, cv::Size (3, 3), 1.0, 1.0); img_gauss_max = max (img, img_gauss_max);*/ } GaussianBlur (img_max, img_max_gauss, cv::Size (3, 3), 1.0, 1.0); applyColorMap (img_max, imgc_max, COLORMAP_JET); applyColorMap (img_max_gauss, imgc_max_gauss, COLORMAP_JET); applyColorMap (img_gauss_max, imgc_gauss_max, COLORMAP_JET); //while (true) { //scanf ("%lf %lf", &lowThreshold, &uppThreshold); //do_canny (img_max, img_max_canny); //do_canny (img_gauss_max, img_gauss_max_canny); /*img_max_watershed.create (n, m, CV_32SC1); img_max_watershed.setTo (0);*/ //ex_watershed (imgc_max); //watershed (img_gauss_max, img_gauss_max_watershed); //GaussianBlur (img_max, img_max_gauss, cv::Size (9, 9), 1.0, 1.0); //do_canny (img_max_gauss, img_max_gauss_canny); //watershed (img_max_gauss, img_max_gauss_watershed); /* imshow ("0. bm3d 1. max 2. jet", imgc_max); imshow ("0. bm3d 1. max 2. gauss: 3. jet", imgc_max_gauss); imshow ("0. bm3d 1. gauss 2. max: ", imgc_gauss_max); */ // Canny view /* imshow ("1. max 2. canny", img_max_canny); imshow ("1. max 2. gauss 3. canny", img_max_gauss_canny); imshow ("1. gauss 2. max 3. canny ", img_gauss_max_canny); */ /*double minVal, maxVal; img_max_watershed += 1; minMaxLoc (img_max_watershed, &minVal, &maxVal); Mat imgc_watershed; img_max_watershed.convertTo (imgc_watershed, CV_8U, 255.0 / (maxVal - minVal), -minVal * 255.0 / (maxVal - minVal));*/ //applyColorMap (imgc_watershed, imgc_watershed, COLORMAP_JET); // Watershed view //imshow ("1. max 2. watershed", imgc_watershed); /*imshow ("1. max 2. gauss 3. watershed", img_max_gauss_watershed); imshow ("1. gauss 2. max 3. watershed ", img_gauss_max_watershed);*/ //int key = waitKey (); //} //int x = (int)string (matfilename).find ('.'); //string file_name = string (matfilename).substr (0, x); //CreateDirectory (file_name.c_str (), 0); //CreateDirectory (, 0); //fs::create_directories ((file_name + "\\Max")); //string path = matfiledir + "\\" + file_name + "\\Max"; //file_name = ""; Mat img_thresh; //threshold (img_max, img_thresh, threshold_value, threshold_max_value, THRESH_TOZERO | CV_THRESH_OTSU); //imshow ("some", img_max); imshow ("max thr", img_thresh); //threshold (img_max_gauss, img_thresh, 0, threshold_max_value, THRESH_TOZERO | CV_THRESH_OTSU); imshow ("max gauss thr", img_thresh); //threshold (img_gauss_max, img_thresh, 0, threshold_max_value, THRESH_TOZERO | CV_THRESH_OTSU); imshow ("gauss max thr", img_thresh); /* imwrite (path + "\\" + "1_max__" + file_name + ".bmp", img_max); imwrite (path + "\\" + "2_max_gauss__" + file_name + ".bmp", img_max_gauss); imwrite (path + "\\" + "3_gauss_max__" + file_name + ".bmp", img_gauss_max); imwrite (path + "\\" + "1_max_jet__" + file_name + ".bmp", imgc_max); imwrite (path + "\\" + "2_max_gauss_jet__" + file_name + ".bmp", imgc_max_gauss); imwrite (path + "\\" + "3_gauss_max_jet__" + file_name + ".bmp", imgc_gauss_max); Mat img_max_thr, img_max_gauss_thr, img_gauss_max_thr; my_threshold (img_max, img_max_thr); my_threshold (img_max_gauss, img_max_gauss_thr); my_threshold (img_gauss_max, img_gauss_max_thr); imwrite (path + "\\" + "1_max_thr__" + file_name + ".bmp", img_max_thr); imwrite (path + "\\" + "2_max_gauss_thr__" + file_name + ".bmp", img_max_gauss_thr); imwrite (path + "\\" + "3_gauss_max_thr__" + file_name + ".bmp", img_gauss_max_thr); */ /*// Canny save imwrite (path + "\\" + "1_max_canny__" + file_name + ".bmp", img_max_canny); imwrite (path + "\\" + "2_max_gauss_canny__" + file_name + ".bmp", img_max_gauss_canny); imwrite (path + "\\" + "3_gauss_max_canny__" + file_name + ".bmp", img_gauss_max_canny);*/ int key = waitKey (); destroyAllWindows (); return 0; }
Mat ScreenDetector::getTransformationMatrix(Error& error) { bool approxFound = false; // convert image to HSV cvtColor(img, hsv, CV_BGR2HSV); // threshold the image inRange(hsv, hsvMin, hsvMax, thresholded); // Optimize threshold by reducing noise erode(thresholded, thresholded, getStructuringElement(MORPH_ELLIPSE, Size(erodeDilateSize, erodeDilateSize)) ); dilate( thresholded, thresholded, getStructuringElement(MORPH_ELLIPSE, Size(erodeDilateSize, erodeDilateSize)) ); dilate( thresholded, thresholded, getStructuringElement(MORPH_ELLIPSE, Size(erodeDilateSize, erodeDilateSize)) ); erode(thresholded, thresholded, getStructuringElement(MORPH_ELLIPSE, Size(erodeDilateSize, erodeDilateSize)) ); GaussianBlur(thresholded, thresholded, Size(3,3), 0); Mat forContours; thresholded.copyTo(forContours); // find all contours Contours contours; Contour approximatedScreen; findContours(forContours, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); int nbContours = contours.size(); cout << nbContours << " contours found, debug: " << DEBUG << endl; if(nbContours == 0) { error.setError("Unable to find the screen", "The camera doesn't detect any screen or green element." "Please check if your screen is turned on and directed toward the screen"); return img; } sort(contours.begin(), contours.end(), contour_compare_area); // find the contour with the biggest area that have 4 points when approximated for(int i=0; i < nbContours; ++i) { approxPolyDP(contours.at(i), approximatedScreen, approximateEpsilon * arcLength(contours.at(i), true), true); // our screen has 4 point when approximated if(approximatedScreen.size() == 4) { approxFound = true; break; } } if(!approxFound) { error.setError("Unable to find the screen properly", "It seems that the screen is not fully detectable by the camera. Try to reduce light in your room"); return img; } if(DEBUG) { namedWindow("debug", WINDOW_KEEPRATIO); namedWindow("thresholded_calibration", WINDOW_KEEPRATIO); Mat debug = Mat::zeros(img.rows, img.cols, CV_8UC3); polylines(debug, approximatedScreen, true, Scalar(0,0,255), 3); imshow("debug", debug); imshow("thresholded_calibration", thresholded); } return transformImage(approximatedScreen); }
int calc_max_thr (unsigned char * data, int n, int m, int nt, int img_type, int type_size) { Mat img_max_gauss, img_gauss_max, img_max; Mat imgc_max_gauss, imgc_gauss_max, imgc_max; img_max.create (n, m, CV_8UC1); img_max.setTo (0); img_gauss_max.create (n, m, CV_8UC1); img_gauss_max.setTo (0); for (int i = 0; i < nt; i++) { Mat img (n, m, img_type, data + i * n * m * type_size); img = min (img, 400); double minVal, maxVal; minMaxLoc (img, &minVal, &maxVal); //find minimum and maximum intensities img.convertTo (img, CV_8U, 255.0 / (maxVal - minVal), -minVal * 255.0 / (maxVal - minVal)); img_max = max (img, img_max); GaussianBlur (img, img, cv::Size (3, 3), 1.0, 1.0); img_gauss_max = max (img, img_gauss_max); } GaussianBlur (img_max, img_max_gauss, cv::Size (3, 3), 1.0, 1.0); applyColorMap (img_max, imgc_max, COLORMAP_JET); applyColorMap (img_max_gauss, imgc_max_gauss, COLORMAP_JET); applyColorMap (img_gauss_max, imgc_gauss_max, COLORMAP_JET); //int x = (int)string (matfilename).find ('.'); //string file_name = string (matfilename).substr (0, x); //CreateDirectory (file_name.c_str (), 0); //CreateDirectory ((file_name + "\\Max").c_str (), 0); //string path = matfiledir + "\\" + file_name + "\\Max"; /*imwrite (path + "\\" + "1_max__" + file_name + ".bmp", img_max); imwrite (path + "\\" + "2_max_gauss__" + file_name + ".bmp", img_max_gauss); imwrite (path + "\\" + "3_gauss_max__" + file_name + ".bmp", img_gauss_max); imwrite (path + "\\" + "1_max_jet__" + file_name + ".bmp", imgc_max); imwrite (path + "\\" + "2_max_gauss_jet__" + file_name + ".bmp", imgc_max_gauss); imwrite (path + "\\" + "3_gauss_max_jet__" + file_name + ".bmp", imgc_gauss_max); */ Mat img_max_thr, img_max_gauss_thr, img_gauss_max_thr; my_threshold (img_max, img_max_thr); my_threshold (img_max_gauss, img_max_gauss_thr); my_threshold (img_gauss_max, img_gauss_max_thr); /*imwrite (path + "\\" + "1_max_thr_100__" + file_name + ".bmp", img_max_thr); imwrite (path + "\\" + "2_max_gauss_thr_100__" + file_name + ".bmp", img_max_gauss_thr); imwrite (path + "\\" + "3_gauss_max_thr_100__" + file_name + ".bmp", img_gauss_max_thr); my_threshold (img_max, img_max_thr, true); my_threshold (img_max_gauss, img_max_gauss_thr, true); my_threshold (img_gauss_max, img_gauss_max_thr, true); imwrite (path + "\\" + "1_max_thr_otsu__" + file_name + ".bmp", img_max_thr); imwrite (path + "\\" + "2_max_gauss_thr_otsu__" + file_name + ".bmp", img_max_gauss_thr); imwrite (path + "\\" + "3_gauss_max_thr_otsu__" + file_name + ".bmp", img_gauss_max_thr);*/ return 0; }
Mat visionUtils::skinDetect(Mat captureframe, Mat3b *skinDetectHSV, Mat *skinMask, std::vector<int> adaptiveHSV, int minPixelSize, int imgBlurPixels, int imgMorphPixels, int singleRegionChoice, bool displayFaces) { if (adaptiveHSV.size()!=6 || adaptiveHSV.empty()) { adaptiveHSV.clear(); adaptiveHSV.push_back(5); adaptiveHSV.push_back(38); adaptiveHSV.push_back(51); adaptiveHSV.push_back(17); adaptiveHSV.push_back(250); adaptiveHSV.push_back(242); } //int step = 0; Mat3b frameTemp; Mat3b frame; // Forcing resize to 640x480 -> all thresholds / pixel filters configured for this size..... // Note returned to original size at end... Size s = captureframe.size(); cv::resize(captureframe,captureframe,Size(640,480)); if (useGPU) { GpuMat imgGPU, imgGPUHSV; imgGPU.upload(captureframe); cv::cvtColor(imgGPU, imgGPUHSV, CV_BGR2HSV); GaussianBlur(imgGPUHSV, imgGPUHSV, Size(imgBlurPixels,imgBlurPixels), 1, 1); imgGPUHSV.download(frameTemp); } else { cv::cvtColor(captureframe, frameTemp, CV_BGR2HSV); GaussianBlur(frameTemp, frameTemp, Size(imgBlurPixels,imgBlurPixels), 1, 1); } // Potential FASTER VERSION using inRange Mat frameThreshold = Mat::zeros(frameTemp.rows,frameTemp.cols, CV_8UC1); Mat hsvMin = (Mat_<int>(1,3) << adaptiveHSV[0], adaptiveHSV[1],adaptiveHSV[2] ); Mat hsvMax = (Mat_<int>(1,3) << adaptiveHSV[3], adaptiveHSV[4],adaptiveHSV[5] ); inRange(frameTemp,hsvMin ,hsvMax, frameThreshold); frameTemp.copyTo(frame,frameThreshold); /* BGR CONVERSION AND THRESHOLD */ Mat1b frame_gray; // send HSV to skinDetectHSV for return *skinDetectHSV=frame.clone(); cv::cvtColor(frame, frame_gray, CV_BGR2GRAY); // Adaptive thresholding technique // 1. Threshold data to find main areas of skin adaptiveThreshold(frame_gray,frame_gray,255,ADAPTIVE_THRESH_GAUSSIAN_C,THRESH_BINARY_INV,9,1); if (useGPU) { GpuMat imgGPU; imgGPU.upload(frame_gray); // 2. Fill in thresholded areas #if CV_MAJOR_VERSION == 2 gpu::morphologyEx(imgGPU, imgGPU, CV_MOP_CLOSE, Mat1b(imgMorphPixels,imgMorphPixels,1), Point(-1, -1), 2); gpu::GaussianBlur(imgGPU, imgGPU, Size(imgBlurPixels,imgBlurPixels), 1, 1); #elif CV_MAJOR_VERSION == 3 //TODO: Check if that's correct Mat element = getStructuringElement(MORPH_RECT, Size(imgMorphPixels, imgMorphPixels), Point(-1, -1)); Ptr<cuda::Filter> closeFilter = cuda::createMorphologyFilter(MORPH_CLOSE, imgGPU.type(), element, Point(-1, -1), 2); closeFilter->apply(imgGPU, imgGPU); cv::Ptr<cv::cuda::Filter> gaussianFilter = cv::cuda::createGaussianFilter(imgGPU.type(), imgGPU.type(), Size(imgMorphPixels, imgMorphPixels), 1, 1); gaussianFilter->apply(imgGPU, imgGPU); #endif imgGPU.download(frame_gray); } else { // 2. Fill in thresholded areas morphologyEx(frame_gray, frame_gray, CV_MOP_CLOSE, Mat1b(imgMorphPixels,imgMorphPixels,1), Point(-1, -1), 2); GaussianBlur(frame_gray, frame_gray, Size(imgBlurPixels,imgBlurPixels), 1, 1); // Select single largest region from image, if singleRegionChoice is selected (1) } if (singleRegionChoice) { *skinMask = cannySegmentation(frame_gray, -1, displayFaces); } else // Detect each separate block and remove blobs smaller than a few pixels { *skinMask = cannySegmentation(frame_gray, minPixelSize, displayFaces); } // Just return skin Mat frame_skin; captureframe.copyTo(frame_skin,*skinMask); // Copy captureframe data to frame_skin, using mask from frame_ttt // Resize image to original before return cv::resize(frame_skin,frame_skin,s); if (displayFaces) { imshow("Skin HSV (B)",frame); imshow("Adaptive_threshold (D1)",frame_gray); imshow("Skin segmented",frame_skin); } return frame_skin; waitKey(1); }
void Dimage::salient_detection() { Mat hsl,h,s,l,hg,lg, blkWhte, grad, img; vector<vector<Point> > contours; Mat src = this->image; Mat cropped; string buffer; GaussianBlur(this->image, img, Size(3, 3), 0, 0, BORDER_DEFAULT); cout << "blurred" << endl; vector<Mat> channels(3); cvtColor(img, hsl, CV_RGB2HLS); split(hsl, channels); cout << "splitted" << endl; h = channels[1]; s = channels[0]; l = channels[2]; hg = gradient(h); lg = gradient(l); grad = h + l; grad = CannyThreshold(grad,grad); h = CannyThreshold(h,h); cout << "thresholded" << endl; grad = (grad & h); /// Find contours findContours(grad, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point(0, 0)); vector<vector<Point> > contours_poly(contours.size()); vector<Rect> boundRect(contours.size()); /// Approximate contours to polygons + get bounding rects and circles cout << "countours found" << endl; cout << contours.size() << endl; for (int i = 0; i < contours.size(); i++) { cout << "i: " << i << endl; if (contourArea(contours.at(i)) < 600) { cout << "in da if" << endl; approxPolyDP(Mat(contours.at(i)), contours_poly.at(i), 3, true); cout << "at roi" << endl; //boundingRect(Mat(contours[i])); Rect roi = boundingRect(Mat(contours.at(i))); /*cropped = src(roi); imshow("Cropped image", cropped); cvWaitKey(0);*/ this->ROI.push_back(roi); cout << "size of victor: " << this->ROI.size() << endl; } } cout << "bounding rect found" << endl; };
static cv::Mat signalDetect_inROI(const cv::Mat& roi, const cv::Mat& src_img, const double estimatedRadius, const cv::Point roi_topLeft ) { /* reduce noise */ cv::Mat noiseReduced(roi.rows, roi.cols, CV_8UC3); GaussianBlur(roi, noiseReduced, cv::Size(3, 3), 0, 0); /* extract color information */ cv::Mat red_mask(roi.rows, roi.cols, CV_8UC1); colorExtraction(noiseReduced , &red_mask , thSet.Red.Hue.lower, thSet.Red.Hue.upper, thSet.Red.Sat.lower, thSet.Red.Sat.upper, thSet.Red.Val.lower, thSet.Red.Val.upper); cv::Mat yellow_mask(roi.rows, roi.cols, CV_8UC1); colorExtraction(noiseReduced , &yellow_mask , thSet.Yellow.Hue.lower, thSet.Yellow.Hue.upper, thSet.Yellow.Sat.lower, thSet.Yellow.Sat.upper, thSet.Yellow.Val.lower, thSet.Yellow.Val.upper); cv::Mat green_mask(roi.rows, roi.cols, CV_8UC1); colorExtraction(noiseReduced , &green_mask , thSet.Green.Hue.lower, thSet.Green.Hue.upper, thSet.Green.Sat.lower, thSet.Green.Sat.upper, thSet.Green.Val.lower, thSet.Green.Val.upper); /* combine all color mask and create binarized image */ cv::Mat binarized = cv::Mat::zeros(roi.rows, roi.cols, CV_8UC1); bitwise_or(red_mask, yellow_mask, binarized); bitwise_or(binarized, green_mask, binarized); threshold(binarized, binarized, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU); /* filter by its shape and index each bright region */ std::vector< std::vector<cv::Point> > bright_contours; std::vector<cv::Vec4i> bright_hierarchy; findContours(binarized, bright_contours, bright_hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE); cv::Mat bright_mask = cv::Mat::zeros(roi.rows, roi.cols, CV_8UC1); int contours_idx = 0; std::vector<regionCandidate> candidates; for (unsigned int i=0; i<bright_contours.size(); i++) { cv::Rect bound = boundingRect(bright_contours.at(contours_idx)); cv::Scalar rangeColor = BLACK; struct regionCandidate cnd; double area = contourArea(bright_contours.at(contours_idx)); double perimeter = arcLength(bright_contours.at(contours_idx), true); double circleLevel = (IsNearlyZero(perimeter)) ? 0.0f : (4.0f * CV_PI * area / pow(perimeter, 2)); if (std::max(bound.width, bound.height) < 2*std::min(bound.width, bound.height) && /* dimension ratio */ CIRCLE_LEVEL_THRESHOLD <= circleLevel && CIRCLE_AREA_THRESHOLD <= area) { // std::cerr << "circleLevel: " << circleLevel << std::endl; rangeColor = WHITE; cnd.center.x = bound.x + bound.width/2; cnd.center.y = bound.y + bound.height/2; cnd.idx = contours_idx; cnd.circleLevel = (IsNearlyZero(perimeter)) ? 0.0f : (4.0 * CV_PI * area / pow(perimeter, 2)); cnd.isBlacked = false; candidates.push_back(cnd); } drawContours(bright_mask, bright_contours, contours_idx, rangeColor, CV_FILLED, 8, bright_hierarchy, 0); /* only contours on toplevel are considered */ contours_idx = bright_hierarchy[contours_idx][0]; if (contours_idx < 0) break; } // imshow("bright_mask", bright_mask); // waitKey(10); unsigned int candidates_num = candidates.size(); // std::cerr << "before checkExtrinctionLight. candidates: " << candidates_num << std::endl; /* decrease candidates by checking existence of turned off light in their neighborhood */ if (candidates_num > 1) /* if there are multipule candidates */ { for (unsigned int i=0; i<candidates.size(); i++) { /* check wheter this candidate seems to be green lamp */ cv::Point check_roi_topLeft = cv::Point(candidates.at(i).center.x - 2*estimatedRadius + roi_topLeft.x, candidates.at(i).center.y - 2*estimatedRadius + roi_topLeft.y); cv::Point check_roi_botRight = cv::Point(candidates.at(i).center.x + 6*estimatedRadius + roi_topLeft.x, candidates.at(i).center.y + 2*estimatedRadius + roi_topLeft.y); bool likeGreen = checkExtinctionLight(src_img, check_roi_topLeft, check_roi_botRight, candidates.at(i).center); /* check wheter this candidate seems to be yellow lamp */ check_roi_topLeft = cv::Point(candidates.at(i).center.x - 4*estimatedRadius + roi_topLeft.x, candidates.at(i).center.y - 2*estimatedRadius + roi_topLeft.y); check_roi_botRight = cv::Point(candidates.at(i).center.x + 4*estimatedRadius + roi_topLeft.x, candidates.at(i).center.y + 2*estimatedRadius + roi_topLeft.y); bool likeYellow = checkExtinctionLight(src_img, check_roi_topLeft, check_roi_botRight, candidates.at(i).center); /* check wheter this candidate seems to be red lamp */ check_roi_topLeft = cv::Point(candidates.at(i).center.x - 6*estimatedRadius + roi_topLeft.x, candidates.at(i).center.y - 2*estimatedRadius + roi_topLeft.y); check_roi_botRight = cv::Point(candidates.at(i).center.x + 2*estimatedRadius + roi_topLeft.x, candidates.at(i).center.y + 2*estimatedRadius + roi_topLeft.y); bool likeRed = checkExtinctionLight(src_img, check_roi_topLeft, check_roi_botRight, candidates.at(i).center); if (!likeGreen && !likeYellow && !likeRed) /* this region may not be traffic light */ { candidates_num--; drawContours(bright_mask, bright_contours, candidates.at(i).idx, BLACK, CV_FILLED, 8, bright_hierarchy, 0); candidates.at(i).isBlacked = true; } } } // std::cerr << "after checkExtrinctionLight. candidates: " << candidates_num << std::endl; /* choose one candidate by comparing degree of circularity */ if (candidates_num > 1) /* if there are still multiple candidates */ { double min_diff = DBL_MAX; unsigned int min_idx = 0; /* search the region that has nearest degree of circularity to 1 */ for (unsigned int i=0; i<candidates.size(); i++) { if(candidates.at(i).isBlacked) continue; double diff = fabs(1 - candidates.at(i).circleLevel); if (min_diff > diff) { min_diff = diff; min_idx = i; } } /* fill region of non-candidate */ for (unsigned int i=0; i<candidates.size(); i++) { if(candidates.at(i).isBlacked) continue; cv::Scalar regionColor = BLACK; candidates.at(i).isBlacked = true; if (i == min_idx) { regionColor = WHITE; candidates.at(i).isBlacked = false; } drawContours(bright_mask, bright_contours, candidates.at(i).idx, regionColor, CV_FILLED, 8, bright_hierarchy, 0); } } return bright_mask; } /* static void signalDetect_inROI() */
int main(int argc, char ** argv) { string gauss = "Gaussino"; string canny = "Canny"; string hough = "Hough"; string binarizar = "Binarizar"; string Otsu = "Otsu"; string image_name = ""; int number; Point min, max, start; ofstream myfile; myfile.open("data.txt"); myfile << "ESCREVE QUALQUER COISA\n"; clock_t t1, t2, t3, t4; double threshold1, threshold2, thres, minLength, maxGap; bool f1, f2, f3, f4, f5, f6, f7, f8, f9; string Result; ostringstream convert; //int i; float temp; //for (i = 1; i <= 6; i++){ //number = i; //convert << number; //Result = convert.str(); //image_name = "a" + Result + ".JPG"; image_name = "a2.JPG"; //number++; //cout << number << endl; cout << image_name; myfile << image_name; myfile << "\n"; t1 = clock(); f1 = false; f2 = true; f3 = false; f4 = false; f5 = false; f6 = true; f7 = true; if (f7 == true){ threshold1 = 10; threshold2 = 19; } f8 = false; f9 = true; if (f9 == true){ thres = 10;// 40 minLength = 20; //50 maxGap = 30; //80 /* CvCapture* capture = cvCaptureFromCAM( CV_CAP_ANY ); if ( !capture ) { fprintf( stderr, "ERROR: capture is NULL \n" ); getchar(); return -1; } string original = "original.jpg"; string foto ="img"; IplImage* frame = cvQueryFrame( capture ); Mat img(frame); Mat I, I1, imge; cvtColor(img,imge,CV_RGB2GRAY); imge.convertTo(I, CV_8U); equalizeHist(I,I1); Mat aux = I1; savePictures(I1, original, foto); */ //realiza a leitura e carrega a imagem para a matriz I1 // a imagem tem apenas 1 canal de cor e por isso foi usado o parametro CV_LOAD_IMAGE_GRAYSCALE Mat lara = imread("lara.JPG", CV_LOAD_IMAGE_GRAYSCALE); Mat I = imread(image_name, CV_LOAD_IMAGE_GRAYSCALE); if (I.empty()) return -1; resize(I, I, lara.size(), 1.0, 1.0, INTER_LINEAR); Mat I1; //Mat aux = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE); equalizeHist(I, I1); Mat aux, original; aux = I1; //ShowImage(I, I1); // verifica se carregou e alocou a imagem com sucesso if (I1.empty()) return -1; // tipo Size contem largura e altura da imagem, recebe o retorno do metodo .size() //imSize = I1.size(); // Cria uma matriz do tamanho imSize, de 8 bits e 1 canal Mat I2 = Mat::zeros(I1.size(), CV_8UC1); if (f2 == true) { t2 = clock(); for (int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2) GaussianBlur(I1, I1, Size(i, i), 0, 0, BORDER_DEFAULT); //ShowImage(aux, I1); cout << "Guassiano tempo : "; temp = tempo(t2); savePictures(I1, image_name, gauss); myfile << "Gauss: "; myfile << temp; myfile << "\n"; } if (f1 == true){ t2 = clock(); binarizacao(I1, 125); //ShowImage(aux, I1); cout << "binarizacao : "; temp = tempo(t2); savePictures(I1, image_name, binarizar); myfile << "Binarizacao: "; myfile << temp; myfile << "\n"; } if (f3 == true){ t2 = clock(); inversao(I1); cout << "inversao : "; tempo(t2); } if (f4 == true){ adaptiveThreshold(I1, I1, 255, ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, 7, 0); } if (f5 == true) Laplacian(I1, I1, 125, 1, 1, 0, BORDER_DEFAULT); if (f7 == true){ t2 = clock(); Canny(I1, I2, threshold1, threshold2, 3, false); cout << "canny : "; temp = tempo(t2); savePictures(I2, image_name, canny); myfile << "Canny: " + (int)(temp * 1000); myfile << "\n"; } if (f9 == true){ t2 = clock(); Hough(I2, aux, thres, minLength, maxGap); cout << "hough : "; temp = tempo(t2); savePictures(aux, image_name, hough); myfile << "Hough: "; myfile << temp; myfile << "\n"; } if (f6 == true){ t2 = clock(); threshold_type = THRESH_BINARY; threshold(aux, I1, 9, max_BINARY_value, threshold_type); cout << "Threshold : "; //savePictures(aux, image_name, Otsu); temp = tempo(t2); myfile << "Threshold/OTSU: "; myfile << temp; myfile << "\n"; } string name = Otsu + image_name; imwrite(name, aux); ShowImage(I1, aux); t2 = clock(); max = maxPoint(aux); min = minPoint(aux); /*start.y = (max.y + min.y) / 2; start.x = (max.x + min.x) /2;*/ start.x = max.x; start.y = max.y; Point end; end.x = start.x; end.y = aux.size().height; MyLine(I, start, end, image_name, 0.3); temp = tempo(t2); ShowImage(I, aux); myfile << "Rota: "; myfile << temp; myfile << "\n"; temp = tempo(t1); cout << "Final time : "; myfile << "Final Time: "; myfile << temp; myfile << "\n"; //float angle = Angle(aux, min, 5); //cout << angle; } //} myfile.close(); //ShowImage(aux, I1); //imwrite(argv[2], I2); // salva imagem I2 no arquivo definido pelo usuario em argv[2] //} return 0; }
void VirtualSurgeon_Warp::doWarp(VirtualSurgeonFaceData& model_p, vector<Point2d> face_points, vector<Point2d> model_points, Mat& model_im, Mat& model_mask, Mat& im, Mat& im_mask) { //warp //double model_dist = norm(model_p.li - model_p.ri); //model_dist *= cos(model_p.yaw / 180.0 * CV_PI); //double face_dist = norm(p.li - p.ri); //face_dist *= cos(p.yaw / 180.0 * CV_PI); //double scaleFromFaceToBack = model_dist / face_dist; ////double scaleFromFaceToBack = norm(model_p.li - model_p.ri) / norm(p.li - p.ri); ////Point2d model_midp = (model_p.li + model_p.ri) * .5; ////Point2d face_midp = (p.li + p.ri) * .5; ////Point2d diff = model_midp - face_midp; //Mat facePts(face_points); //facePts = facePts * scaleFromFaceToBack; //Mat modelPts(model_points); //modelPts = modelPts - Scalar(diff.x,diff.y); vector<Mat* > imgs; Mat backM,maskM; model_im.copyTo(backM); model_mask.copyTo(maskM); imgs.push_back(&(backM)); imgs.push_back(&(maskM)); //warp back into face face_warp(imgs, face_points, model_points, im.size(), (p.use_warp_affine)?FACE_WARP_AFFINE:FACE_WARP_RIGID, (p.use_double_warp)?0.75:1.0); GaussianBlur(maskM,maskM,Size(7,7),1); //blur(maskM,maskM,Size(7,7)); //facePts = Mat(face_points); //facePts = facePts / scaleFromFaceToBack; backM.copyTo(model_im); maskM.copyTo(model_mask); if(p.use_double_warp) { //warp face into back... imgs.clear(); im.copyTo(backM); im_mask.copyTo(maskM); imgs.push_back(&(backM)); imgs.push_back(&(maskM)); face_warp(imgs, model_points, face_points, model_im.size(), (p.use_warp_affine)?FACE_WARP_AFFINE:FACE_WARP_RIGID, 0.25); backM.copyTo(im); maskM.copyTo(im_mask); } }
cv::Point findEyeCenter(cv::Mat face, cv::Rect eye, std::string debugWindow) { cv::Mat eyeROIUnscaled = face(eye); cv::Mat eyeROI; scaleToFastSize(eyeROIUnscaled, eyeROI); // draw eye region rectangle(face,eye,1234); //-- Find the gradient cv::Mat gradientX = computeMatXGradient(eyeROI); cv::Mat gradientY = computeMatXGradient(eyeROI.t()).t(); //-- Normalize and threshold the gradient // compute all the magnitudes cv::Mat mags = matrixMagnitude(gradientX, gradientY); //compute the threshold double gradientThresh = computeDynamicThreshold(mags, kGradientThreshold); //double gradientThresh = kGradientThreshold; //double gradientThresh = 0; //normalize for (int y = 0; y < eyeROI.rows; ++y) { double *Xr = gradientX.ptr<double>(y), *Yr = gradientY.ptr<double>(y); const double *Mr = mags.ptr<double>(y); for (int x = 0; x < eyeROI.cols; ++x) { double gX = Xr[x], gY = Yr[x]; double magnitude = Mr[x]; if (magnitude > gradientThresh) { Xr[x] = gX/magnitude; Yr[x] = gY/magnitude; } else { Xr[x] = 0.0; Yr[x] = 0.0; } } } //-- Create a blurred and inverted image for weighting cv::Mat weight; GaussianBlur( eyeROI, weight, cv::Size( kWeightBlurSize, kWeightBlurSize ), 0, 0 ); for (int y = 0; y < weight.rows; ++y) { unsigned char *row = weight.ptr<unsigned char>(y); for (int x = 0; x < weight.cols; ++x) { row[x] = (255 - row[x]); } } //imshow(debugWindow,weight); //-- Run the algorithm! cv::Mat outSum = cv::Mat::zeros(eyeROI.rows,eyeROI.cols,CV_64F); // for each possible center // printf("Eye Size: %ix%i\n",outSum.cols,outSum.rows); for (int y = 0; y < weight.rows; ++y) { const unsigned char *Wr = weight.ptr<unsigned char>(y); const double *Xr = gradientX.ptr<double>(y), *Yr = gradientY.ptr<double>(y); for (int x = 0; x < weight.cols; ++x) { double gX = Xr[x], gY = Yr[x]; if (gX == 0.0 && gY == 0.0) { continue; } testPossibleCentersFormula(x, y, Wr[x], gX, gY, outSum); } } // scale all the values down, basically averaging them double numGradients = (weight.rows*weight.cols); cv::Mat out; outSum.convertTo(out, CV_32F,1.0/numGradients); //imshow(debugWindow,out); //-- Find the maximum point cv::Point maxP; double maxVal; cv::minMaxLoc(out, NULL,&maxVal,NULL,&maxP); //-- Flood fill the edges if(kEnablePostProcess) { cv::Mat floodClone; //double floodThresh = computeDynamicThreshold(out, 1.5); double floodThresh = maxVal * kPostProcessThreshold; cv::threshold(out, floodClone, floodThresh, 0.0f, cv::THRESH_TOZERO); if(kPlotVectorField) { //plotVecField(gradientX, gradientY, floodClone); imwrite("eyeFrame.png",eyeROIUnscaled); } cv::Mat mask = floodKillEdges(floodClone); //imshow(debugWindow + " Mask",mask); //imshow(debugWindow,out); // redo max cv::minMaxLoc(out, NULL,&maxVal,NULL,&maxP,mask); } return unscalePoint(maxP,eye); }
int main(int argc, char** argv) { int ratio = 3; int kernel_size = 3; int sigma = 200; //connection to camera CvCapture* capture = cvCaptureFromCAM(CV_CAP_ANY); if(!capture) { std::cerr << "ERROR: capture is NULL\n"; getchar(); return -1; } /* ONLY NEEDED FOR TESTING PURPOSES cvNamedWindow("Camera Image", CV_WINDOW_AUTOSIZE); // Create a Trackbar for user to enter threshold cv::createTrackbar("Min Threshold:","Camera Image" , &lowThreshold, max_lowThreshold, DummyCallback); // Create a Trackbar for user to enter threshold cv::createTrackbar("Hough Threshold:","Camera Image" , &houghThreshold, max_houghThreshold, DummyCallback); // Create a Trackbar for user to enter threshold cv::createTrackbar("Sigma:","Camera Image" , &sigma, 1000, DummyCallback); cvNamedWindow("Edge Image", CV_WINDOW_AUTOSIZE); */ ros::init(argc,argv, "circle_publisher"); ros::NodeHandle nh; //Let's publish messages as defined in /msg/cirlce.msg on a topic called 'detected_circles' with a max. buffer of 1000 messages ros::Publisher circle_publisher = nh.advertise<circle_detection::circle_msg>("detected_circles",1000); ros::Rate loop_rate(10); //used to create an Image Id size_t id_count = 0; while(ros::ok) { // Get a frame IplImage* frame = cvQueryFrame(capture); if (!frame) { std::cerr << "ERROR: frame is null...\n" ; getchar(); break; } // image id id_count++; cv::Mat src(frame); cv::Mat src_gray; cv::Mat dst; cv::Mat detected_edges; dst.create(src.size(), src.type()); // covert the image to gray cvtColor(src,src_gray,CV_BGR2GRAY); // Reduce the noise so we avoid false circle detection GaussianBlur(src_gray, detected_edges, cv::Size(9, 9), sigma/100.0, 0); equalizeHist(detected_edges, detected_edges); // Canny detector Canny(detected_edges, detected_edges, lowThreshold, lowThreshold*ratio, kernel_size); // Using Canny's output as a mask, we display our result dst = cv::Scalar::all(0); src.copyTo(dst, detected_edges); std::vector<Point> edgePoints; // iterate through the pixels of the canny image for(int j=0;j<detected_edges.cols;j++) { for(int i=0;i<detected_edges.rows;i++) { unsigned char &color = *(detected_edges.data+detected_edges.step*i + j*detected_edges.elemSize()); unsigned char &bb = *(src.data+src.step*i + j*src.elemSize()); unsigned char &gg = *(src.data+src.step*i + j*src.elemSize() + 1); unsigned char &rr = *(src.data+src.step*i + j*src.elemSize() + 2); // check if the pixel is black or white (only edges are white) if(color) { int max = max3(rr,gg,bb); int min = min3(rr,gg,bb); int delta = max - min; // check saturation (only colorfull circles will be detacted if(delta > 20) { edgePoints.push_back(Point((double) j,(double) i)); } else { // mark pixel as no longer relevant, i.e. the pixel isn't recognized as edge color = 0; } } } } std::vector<Circle> detectedCircles; /* Apply the RANSAC algorithm to find circles in the camera image * Paramters: sink vector, points, eps, iterations, minSupporters, maxCircles */ ransac(detectedCircles, edgePoints, 5.0, 10000, 100, 1); /* ONLY NEDDED FOR TESTIGN PURPOSES // Draw the circles detected for(size_t i = 0; i < detectedCircles.size(); i++) { cv::Point center(cvRound(detectedCircles[i].center.x), cvRound(detectedCircles[i].center.y)); int radius = cvRound(detectedCircles[i].radius); // assert(radius > 0); // circle center circle(src, center, 3, cv::Scalar(0,255,0), -1, 8, 0 ); // circle outline circle(src, center, radius, cv::Scalar(0,0,255), 3, 8, 0 ); } //Results imshow("Camera Image", src); imshow("Edge Image", detected_edges); */ for(size_t i=0;i < detectedCircles.size();i++) { circle_detection::circle_msg msg; std::stringstream ss; ss << "IMG" << id_count; msg.image_id = ss.str(); unsigned int radius = cvRound(detectedCircles[i].radius); msg.radius = radius; msg.center_x = cvRound(detectedCircles[i].center.x) ; msg.center_y = cvRound(detectedCircles[i].center.y); circle_publisher.publish(msg); ros::spinOnce(); loop_rate.sleep(); } //Do not release the frame! //If ESC key pressed, Key=0x10001B under OpenCV 0.9.7(linux version), //remove higher bits using AND operator //cvWaitKey() is used as delay between the frames if ( (cvWaitKey(100) & 255) == 27 ) break; } /* ONLY NEEDED FOR TESTING PURPOSES // Release the capture device housekeeping cvReleaseCapture( &capture ); cvDestroyWindow( "Display Image" ); */ return 0; }
cv::Point findEyeCenter(cv::Mat face, cv::Rect eye, std::string debugWindow) { cv::Mat eyeROIUnscaled = face(eye); cv::Mat eyeROI; if(GBStatus) { cv::GaussianBlur( face, face, cv::Size(3,3), 0, 0, cv::BORDER_DEFAULT ); } if(debugL1 && GBStatus && (debugWindow == costado)) { std::string gaussianBlur_window = "GaussianBlur"; cv::namedWindow(gaussianBlur_window,CV_WINDOW_NORMAL); cv::moveWindow(gaussianBlur_window, gaussBlurx, gaussBlury); imshow(gaussianBlur_window,face); } scaleToFastSize(eyeROIUnscaled, eyeROI); // draw eye region rectangle(face,eye,1234); //-- Find the gradient cv::Mat gradientX; cv::Mat gradientY; if(sobel) { cv::Sobel( eyeROIUnscaled, gradientX, ddepth, 1, 0, 3, scale, delta, cv::BORDER_DEFAULT ); // cv::Sobel( (eyeROI.t()).t(), gradientY, ddepth, 0, 1, 3, scale, delta, cv::BORDER_DEFAULT ); cv::Sobel (eyeROIUnscaled, gradientY, ddepth, 0, 1, 3, scale, delta, cv::BORDER_DEFAULT ); } if(maxgradient) { gradientX = computeMatXGradient(eyeROI); gradientY = computeMatXGradient(eyeROI.t()).t(); } calculos("Gradient Y",gradientY); cv::Mat abs_grad_x, abs_grad_y; cv::convertScaleAbs( gradientX, abs_grad_x ); cv::convertScaleAbs( gradientY, abs_grad_y ); calculos("Valor absoluto Gradient Y",abs_grad_y); // cv::Mat gradientY = computeMatXGradient(eyeROI); //-- Normalize and threshold the gradient // compute all the magnitudes cv::Mat mags; if(debugL6) { mags = matrixMagnitude(gradientX, gradientY); } else { addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, mags ); } calculos("Sobel",mags); //compute the threshold double gradientThresh = computeDynamicThreshold(mags, kGradientThreshold); //double gradientThresh = kGradientThreshold; //double gradientThresh = 0; //normalize if(debugL1 && (debugWindow == costado)) { /////////// std::string eyeROI_window = debugWindow; /////////// cv::namedWindow(eyeROI_window,CV_WINDOW_NORMAL); /////////// cv::moveWindow(eyeROI_window, 640, 350); /////////// imshow(eyeROI_window,eyeROI); std::string Sobel_window = "Salida del Filtro"; cv::namedWindow(Sobel_window,CV_WINDOW_NORMAL); cv::moveWindow(Sobel_window, sobelx, sobely); imshow(Sobel_window,mags); } for (int y = 0; y < eyeROI.rows; ++y) { double *Xr = gradientX.ptr<double>(y), *Yr = gradientY.ptr<double>(y); const double *Mr = mags.ptr<double>(y); for (int x = 0; x < eyeROI.cols; ++x) { double gX = Xr[x], gY = Yr[x]; double magnitude = Mr[x]; if (magnitude > gradientThresh) { Xr[x] = gX/magnitude; Yr[x] = gY/magnitude; } else { Xr[x] = 0.0; Yr[x] = 0.0; } } } if(debugL4) { // imshow(debugWindow,gradientX); } //-- Create a blurred and inverted image for weighting cv::Mat weight; GaussianBlur( eyeROI, weight, cv::Size( kWeightBlurSize, kWeightBlurSize ), 0, 0 ); for (int y = 0; y < weight.rows; ++y) { unsigned char *row = weight.ptr<unsigned char>(y); for (int x = 0; x < weight.cols; ++x) { row[x] = (255 - row[x]); } } if(debugL4) { imshow(debugWindow,weight); } //-- Run the algorithm! cv::Mat outSum = cv::Mat::zeros(eyeROI.rows,eyeROI.cols,CV_64F); // for each possible center // printf("Eye Size: %ix%i\n",outSum.cols,outSum.rows); if(debugL4) { imshow("outSum",outSum); } for (int y = 0; y < weight.rows; ++y) { const unsigned char *Wr = weight.ptr<unsigned char>(y); const double *Xr = gradientX.ptr<double>(y), *Yr = gradientY.ptr<double>(y); for (int x = 0; x < weight.cols; ++x) { double gX = Xr[x], gY = Yr[x]; if (gX == 0.0 && gY == 0.0) { continue; } testPossibleCentersFormula(x, y, Wr[x], gX, gY, outSum); } } // scale all the values down, basically averaging them double numGradients = (weight.rows*weight.cols); cv::Mat out; outSum.convertTo(out, CV_32F,1.0/numGradients); if(debugL4) { imshow(debugWindow,outSum); } //-- Find the maximum point cv::Point maxP; double maxVal; cv::minMaxLoc(out, NULL,&maxVal,NULL,&maxP); //-- Flood fill the edges if(kEnablePostProcess) { cv::Mat floodClone; //double floodThresh = computeDynamicThreshold(out, 1.5); double floodThresh = maxVal * kPostProcessThreshold; cv::threshold(out, floodClone, floodThresh, 0.0f, cv::THRESH_TOZERO); if(kPlotVectorField) { //plotVecField(gradientX, gradientY, floodClone); imwrite("eyeFrame.png",eyeROIUnscaled); } cv::Mat mask = floodKillEdges(floodClone); if(debugL4) { imshow(debugWindow + " Mask",mask); // imshow(debugWindow,out); //redo max; } cv::minMaxLoc(out, NULL,&maxVal,NULL,&maxP,mask); } cv::circle(eyeROI, maxP, 3,cv::Scalar(0,0,255)); if(debugL1 && (debugWindow == costado)) { calculos("EyeROI", eyeROI); std::string eyeROI_window = debugWindow; cv::namedWindow(eyeROI_window,CV_WINDOW_NORMAL); cv::moveWindow(eyeROI_window, 640, 350); imshow(eyeROI_window,eyeROI); int c = cv::waitKey(10); if( (char)c == 'g' ) { imwrite("ojo.png",eyeROIUnscaled); } } return unscalePoint(maxP,eye); }
void initKernel(Mat& kernel, const Mat& blurredGray, const int width, const Mat& mask, const int pyrLevel, const int iterations, float thresholdR, float thresholdS) { assert(blurredGray.type() == CV_8U && "gray value image needed"); assert(mask.type() == CV_8U && "mask should be binary image"); // #ifndef NDEBUG // imshow("blurred", blurredGray); // #endif // save min and maximum value of the original image to be able to restore // the latent image with the correct brightness double grayMin; double grayMax; minMaxLoc(blurredGray, &grayMin, &grayMax); // build an image pyramid with gray value images vector<Mat> pyramid, masks; pyramid.push_back(blurredGray); masks.push_back(mask); for (int i = 0; i < (pyrLevel - 1); i++) { Mat downImage, downMask; pyrDown(pyramid[i], downImage, Size(pyramid[i].cols/2, pyramid[i].rows/2)); pyrDown(masks[i], downMask, Size(masks[i].cols/2, masks[i].rows/2)); pyramid.push_back(downImage); masks.push_back(downMask); } // init kernel but in the iterations the tmp-kernel is used kernel = Mat::zeros(width, width, CV_32F); Mat tmpKernel; // go through image pyramid from small to large for (int l = pyramid.size() - 1; l >= 0; l--) { #ifdef IMWRITE imshow("pyr Image", pyramid[l]); double min; double max; minMaxLoc(pyramid[l], &min, &max); cout << "pyr: " << min << " " << max << endl; waitKey(); #endif // compute image gradient for x and y direction // // gaussian blur (in-place operation is supported) GaussianBlur(pyramid[l], pyramid[l], Size(3,3), 0, 0, BORDER_DEFAULT); // parameter for sobel filtering to obtain gradients array<Mat,2> gradients, tmpGradients; const int delta = 0; const int ddepth = CV_32F; const int ksize = 3; const int scale = 1; // gradient x and y Sobel(pyramid[l], tmpGradients[0], ddepth, 1, 0, ksize, scale, delta, BORDER_DEFAULT); Sobel(pyramid[l], tmpGradients[1], ddepth, 0, 1, ksize, scale, delta, BORDER_DEFAULT); // cut off gradients outside the mask tmpGradients[0].copyTo(gradients[0], masks[l]); tmpGradients[1].copyTo(gradients[1], masks[l]); // normalize gradients into range [-1,1] normalizeOne(gradients); // #ifdef IMWRITE // showGradients("x gradient", gradients[0]); // showGradients("y gradient", gradients[1]); // #endif // compute gradient confidence for al pixels Mat gradientConfidence; computeGradientConfidence(gradientConfidence, gradients, width, masks[l]); // #ifdef IMWRITE // showFloat("confidence", gradientConfidence); // #endif // each iterations works on an updated image Mat currentImage; pyramid[l].copyTo(currentImage); // assert(iterations == 1 && "Implement multiple iterations"); for (int i = 0; i < iterations; i++) { #ifdef IMWRITE imshow("current Image", currentImage); minMaxLoc(currentImage, &min, &max); cout << "current: " << min << " " << max << endl; waitKey(); #endif // select edges for kernel estimation (normalized gradients [-1,1]) array<Mat,2> selectedEdges; selectEdges(currentImage, gradientConfidence, thresholdR, thresholdS, selectedEdges); #ifdef IMWRITE showGradients("x gradient selection", selectedEdges[0]); showGradients("y gradient selection", selectedEdges[1]); minMaxLoc(selectedEdges[0], &min, &max); cout << "x gradients: " << min << " " << max << endl; waitKey(); #endif // estimate kernel with gaussian prior fastKernelEstimation(selectedEdges, gradients, kernel, 0.0); #ifdef IMWRITE showFloat("tmp-kernel", kernel, true); minMaxLoc(kernel, &min, &max); cout << "kernel: " << min << " " << max << " sum: " << sum(kernel)[0] << endl; waitKey(); #endif // coarse image estimation with a spatial prior Mat latentImage; // FIXME: it looks like there are some edges of the gradients in the latent image. // with more iterations it becomes worse // coarseImageEstimation(pyramid[l], kernel, selectedEdges, latentImage); // use oother spatial deconv method for now deconvolveIRLS(pyramid[l], latentImage, kernel); #ifdef IMWRITE string name = "two-phase-latent-" + to_string(i); imshow(name, latentImage); waitKey(); string filename = name + ".png"; imwrite(filename, latentImage); #endif // set current image to coarse latent image latentImage.copyTo(currentImage); // decrease thresholds τ_r and τ_s will to include more and more edges thresholdR = thresholdR / 1.1; thresholdS = thresholdS / 1.1; } // set next pyramid image to the upscaled latent image if (l > 0) { Mat upImage; pyrUp(currentImage, upImage, Size(pyramid[l - 1].cols, pyramid[l - 1].rows)); pyramid[l - 1] = upImage; } } // #ifdef IMWRITE // imshow("kernel", kernel); // waitKey(); // #endif }
// get ROI + edgeDectection void FindContour::cellDetection(const Mat &img, vector<Point> &cir_org, Mat &dispImg1, Mat &dispImg2, vector<Point2f> &points1, vector<Point2f> &points2, int &area, int &perimeter, Point2f &ctroid, float &shape, // vector<int> &blebs, int &frameNum){ frame = &img; //rect = boundingRect(Mat(cir)); Mat frameGray; cv::cvtColor(*frame, frameGray, CV_RGB2GRAY); /* QString cellFileName0 = "frame" + QString::number(frameNum) + ".png"; imwrite(cellFileName0.toStdString(), frameGray);*/ vector<Point> cir; //***global coordinates of circle*** for(unsigned int i = 0; i < cir_org.size(); i++){ cir.push_back(Point(cir_org[i].x / scale, cir_org[i].y / scale)); } //cout << "original circle: " << cir_org << "\n" << " scaled circle: " << cir << endl; //enlarge the bounding rect by adding a margin (e) to it rect = enlargeRect(boundingRect(Mat(cir)), 5, img.cols, img.rows); //global circle mask Mat mask_cir_org = Mat::zeros(frame->size(), CV_8UC1); fillConvexPoly(mask_cir_org, cir, Scalar(255)); // flow points vector<unsigned int> cell_pts_global; vector<Point2f> longOptflow_pt1, longOptflow_pt2; Point2f avrg_vec = Point2f(0,0); for(unsigned int i = 0; i < points1.size(); i++){ Point p1 = Point(points1[i].x, points1[i].y); Point p2 = Point(points2[i].x, points2[i].y); if(mask_cir_org.at<uchar>(p1.y,p1.x) == 255 ){ cell_pts_global.push_back(i); if(dist_square(p1, p2) > 2.0){ longOptflow_pt1.push_back(Point2f(p1.x, p1.y)); longOptflow_pt2.push_back(Point2f(p2.x, p2.y)); avrg_vec.x += (p2.x-p1.x); avrg_vec.y += (p2.y-p1.y); } } } // if(longOptflow_pt1.size()!= 0){ // avrg_vec.x = avrg_vec.x / longOptflow_pt1.size(); // avrg_vec.y = avrg_vec.y / longOptflow_pt1.size(); // } Rect trans_rect = translateRect(rect, avrg_vec); // *** // if (the homography is a good one) use the homography to update the rectangle // otherwise use the same rectangle // *** if (longOptflow_pt1.size() >= 4){ Mat H = findHomography(Mat(longOptflow_pt1), Mat(longOptflow_pt2), CV_RANSAC, 2); //cout << "H: " << H << endl; if(determinant(H) >= 0){ vector<Point> rect_corners; rect_corners.push_back(Point(rect.x, rect.y)); rect_corners.push_back(Point(rect.x+rect.width, rect.y)); rect_corners.push_back(Point(rect.x, rect.y+rect.height)); rect_corners.push_back(Point(rect.x+rect.width, rect.y+rect.height)); vector<Point> rect_update_corners = pointTransform(rect_corners, H); trans_rect = boundingRect(rect_update_corners); } } rectangle(frameGray, trans_rect, Scalar(255), 2); imshow("frameGray", frameGray); dispImg1 = (*frame)(rect).clone(); //dispImg2 = Mat(dispImg1.rows, dispImg1.cols, CV_8UC3); Mat sub; //*** the rectangle region of ROI (Gray) *** cv::cvtColor(dispImg1, sub, CV_RGB2GRAY); int width = sub.cols; int height = sub.rows; vector<Point> circle_ROI; //***local coordinates of circle*** for (unsigned int i = 0; i < cir.size(); i++){ Point p = Point(cir[i].x - rect.x, cir[i].y - rect.y); circle_ROI.push_back(p); } Mat adapThreshImg1 = Mat::zeros(height, width, sub.type()); //image edge detection for the sub region (roi rect) adaptiveThreshold(sub, adapThreshImg1, 255.0, ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY_INV, blockSize, constValue); //imshow("adapThreshImg1", adapThreshImg1); // dilation and erosion Mat dilerod; dilErod(adapThreshImg1, dilerod, dilSize); //display image 2 -- dilerod of adaptive threshold image GaussianBlur(dilerod, dilerod, Size(3, 3), 2, 2 ); //mask for filtering out the cell of interest Mat mask_conv = Mat::zeros(height, width, CV_8UC1); fillConvexPoly(mask_conv, circle_ROI, Scalar(255)); //imshow("mask_before", mask_conv); //dilate the mask -> region grows Mat mask_conv_dil; Mat element = getStructuringElement( MORPH_ELLIPSE, Size( 2*2+2, 2*2+1 ), Point(2,2) ); dilate(mask_conv, mask_conv_dil, element); //imshow("mask_dil", mask_conv_dil); /* Mat mask_conv_ero; erode(mask_conv, mask_conv_ero, element); Mat ring_dil, ring_ero; bitwise_xor(mask_conv, mask_conv_dil, ring_dil); bitwise_xor(mask_conv, mask_conv_ero, ring_ero); Mat ring; bitwise_or(ring_dil, ring_ero, ring); imshow("ring", ring); vector<unsigned int> opt_onRing_index; // use optflow info set rectangle for(unsigned int i = 0; i < points2.size(); i++){ Point p2 = Point(points2[i].x, points2[i].y); Point p1 = Point(points1[i].x, points1[i].y); if(ring.at<uchar>(p1.y,p1.x) != 255 && ring.at<uchar>(p2.y,p2.x) != 255) continue; else{ opt_onRing_index.push_back(i); } }*/ /* // draw the optflow on dispImg1 unsigned int size = opt_inside_cl_index.size(); for(unsigned int i = 0; i < size; i++ ){ Point p0( ceil( points1[i].x - rect.x ), ceil( points1[i].y - rect.y ) ); Point p1( ceil( points2[i].x - rect.x ), ceil( points2[i].y - rect.y) ); //std::cout << "(" << p0.x << "," << p0.y << ")" << "\n"; //std::cout << "(" << p1.x << "," << p1.y << ")" << std::endl; //draw lines to visualize the flow double angle = atan2((double) p0.y - p1.y, (double) p0.x - p1.x); double arrowLen = 0.01 * (double) (width); line(dispImg1, p0, p1, CV_RGB(255,255,255), 1 ); Point p; p.x = (int) (p1.x + arrowLen * cos(angle + 3.14/4)); p.y = (int) (p1.y + arrowLen * sin(angle + 3.14/4)); line(dispImg1, p, p1, CV_RGB(255,255,255), 1 ); p.x = (int) (p1.x + arrowLen * cos(angle - 3.14/4)); p.y = (int) (p1.y + arrowLen * sin(angle - 3.14/4)); line(dispImg1, p, Point(2*p1.x - p0.x, 2*p1.y - p0.y), CV_RGB(255,255,255), 1 ); //line(dispImg1, p, p1, CV_RGB(255,255,255), 1 ); }*/ /* //stop growing when meeting with canny edges that outside the circle Mat canny; CannyWithBlur(sub, canny); Mat cannyColor; cvtColor(canny, cannyColor, CV_GRAY2RGB); imwrite("canny.png", canny); vector<Point> outsideCircle; vector<Point> onRing; for(int j = 0; j < height; j++){ for(int i = 0; i < width; i++){ if(canny.at<uchar>(j,i) != 0 && mask_conv.at<uchar>(j,i) == 0){ cannyColor.data[cannyColor.channels()*(cannyColor.cols*j + i)+0] = 81; cannyColor.data[cannyColor.channels()*(cannyColor.cols*j + i)+1] = 172; cannyColor.data[cannyColor.channels()*(cannyColor.cols*j + i)+2] = 251; outsideCircle.push_back(Point(i, j)); if(ring.at<uchar>(j,i) != 0){ cannyColor.data[cannyColor.channels()*(cannyColor.cols*j + i)+0] = 255; cannyColor.data[cannyColor.channels()*(cannyColor.cols*j + i)+1] = 255; cannyColor.data[cannyColor.channels()*(cannyColor.cols*j + i)+2] = 0; onRing.push_back(Point(i,j)); } } } } */ // QString cannyFileName = "canny" + QString::number(frameNum) + ".png"; // imwrite(cannyFileName.toStdString(), cannyColor); //bitwise AND on mask and dilerod bitwise_and(mask_conv/*_dil*/, dilerod, dispImg2); // findcontours vector<vector<Point> > contours; vector<Vec4i> hierarchy; unsigned int largest_contour_index; dilErodContours(dispImg2, contours, hierarchy, largest_contour_index, perimeter, dispImg1); // find the area of the cell by counting the white area inside the largest contour Mat cellArea = Mat::zeros(height, width, CV_8UC1); drawContours(cellArea, contours, largest_contour_index, Scalar(255), -1, 8, hierarchy, 0, Point() ); //imshow("cell", cell); area = countNonZero(cellArea); //cout << "frame " << frameNum << "\n"; //cout << contours[largest_contour_index] << endl; //change dispImg2 from gray to rgb for displaying cvtColor(dispImg2, dispImg2, CV_GRAY2RGB); //renew circle points as the convex hull vector<Point> convHull; convexHull(contours[largest_contour_index], convHull); // find the centroid of the contour Moments mu = moments(contours[largest_contour_index]); ctroid = Point2f(mu.m10/mu.m00 + rect.x, mu.m01/mu.m00 + rect.y); // find the shape of the cell by the largest contour and centroid shape = findShape(ctroid, contours[largest_contour_index]); ////---- draw largest contour start ---- //draw the largest contour Mat borderImg = Mat::zeros(height, width, CV_8UC1); drawContours(borderImg, contours, largest_contour_index, Scalar(255), 1, 8, hierarchy, 0, Point()); //QString cellFileName0 = "border" + QString::number(frameNum) + ".png"; //imwrite(cellFileName0.toStdString(), borderImg); ////---- draw largest contour end ---- // find the number and the sizes of blebs of the cell Mat smooth; vector<Point> smoothCurve; int WIN = 25; vector< vector<Point> > tmp; smooth = curveSmooth(borderImg, WIN, contours[largest_contour_index], smoothCurve, convHull/*ctroid*/); tmp.push_back(smoothCurve); drawContours(dispImg1, tmp, 0, Scalar(255, 0, 0)); bitwise_not(smooth, smooth); Mat blebsImg; bitwise_and(smooth, cellArea, blebsImg); //imshow("blebs", blebs); //QString cellFileName2 = "blebs" + QString::number(frameNum) + ".png"; //imwrite(cellFileName2.toStdString(), blebs); // vector<Point> blebCtrs; // recursive_connected_components(blebsImg, blebs, blebCtrs); // for(unsigned int i = 0; i < blebCtrs.size(); i++){ // circle(dispImg1, blebCtrs[i], 2, Scalar(255, 255, 0)); // } cir_org.clear(); for(unsigned int i = 0; i < convHull.size(); i++) cir_org.push_back(Point((convHull[i].x + rect.x)*scale, (convHull[i].y + rect.y)*scale)); }
int show_flow (unsigned char *data, int n, int m, int nt, int img_type, int type_size) { Point2f point; bool addRemovePt = false; VideoCapture cap; TermCriteria termcrit (CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 20, 0.03); Size subPixWinSize (10, 10), winSize (31, 31); const int MAX_COUNT = 300; bool needToInit = false; bool nightMode = false; Mat gray, prevGray, image; vector<Point2f> points[2]; Mat img_max_gauss, img_gauss_max, img_max; Mat imgc_max_gauss, imgc_gauss_max, imgc_max, img_gauss_max_thr; img_max.create (n, m, CV_8UC1); img_max.setTo (0); img_gauss_max.create (n, m, CV_8UC1); img_gauss_max.setTo (0); for (int i = 0; i < nt; i++) { Mat img (n, m, img_type, data + i * n * m * type_size); img = min (img, 400); double minVal, maxVal; minMaxLoc (img, &minVal, &maxVal); //find minimum and maximum intensities img.convertTo (img, CV_8U, 255.0 / (maxVal - minVal), -minVal * 255.0 / (maxVal - minVal)); img_max = max (img, img_max); GaussianBlur (img, img, cv::Size (3, 3), 1.0, 1.0); img_gauss_max = max (img, img_gauss_max); } threshold (img_gauss_max, img_gauss_max_thr, 0, 255, THRESH_BINARY | CV_THRESH_OTSU); Mat img_gauss_max_thr_res; //resize (img_gauss_max_thr, img_gauss_max_thr_res, cv::Size (img_gauss_max_thr.cols * 3, img_gauss_max_thr.rows * 3), 0, 0, 0); Mat prev_gray, prev_img; //int x = (int)string (matfilename).find ('.'); //string file_name = string (matfilename).substr (0, x); //string path = matfiledir + "\\" + file_name + "\\flow"; //imwrite (path + "\\img_big\\img_gauss_max_thr_res" + +".bmp", img_gauss_max_thr_res); for (int i = 0; i < nt; i++) { printf ("i : %d\n", i); /*Mat frame (n, m, imgtype, data + i * n * m * type_size); frame = min (frame, 100); double minVal, maxVal; minMaxLoc (frame, &minVal, &maxVal); frame.convertTo (frame, CV_8U, 255.0 / (maxVal - minVal), -minVal * 255.0 / (maxVal - minVal)); GaussianBlur (frame, frame, cv::Size (3, 3), 1.0, 1.0); //Mat res_img; //resize (frame, res_img, cv::Size (frame.cols * 3, frame.rows * 3)); //res_img.copyTo (frame); Mat img, image; applyColorMap (frame, img, COLORMAP_JET); img.copyTo (image, img_gauss_max_thr);*/ //frame.copyTo (gray, img_gauss_max_thr); /*Mat img; bitwise_and (image, img_gauss_max_thr, img); image = img;*/ //cvtColor (image, gray, COLOR_BGR2GRAY); Mat flow, cflow; /*if (prev_gray.data != nullptr) { calcOpticalFlowFarneback (prev_gray, gray, flow, 0.5, 5, 10, 1, 5, 1.2, 0); //cvtColor (prev_img, cflow, COLOR_GRAY2BGR); prev_img.copyTo(cflow); draw_optical_flow (flow, cflow, 4, Scalar (0, 100, 0), Scalar (0, 0, 255)); //imshow ("Flow", cflow); //imshow ("gray", gray); //imshow ("prev_gray", prev_gray); char c = (char)waitKey (200); } gray.copyTo (prev_gray); image.copyTo (prev_img);*/ //char c = (char)waitKey (200); /* if (nightMode) image = Scalar::all (0); if (needToInit) { // automatic initialization goodFeaturesToTrack (gray, points[0], MAX_COUNT, 0.01, 10, Mat (), 3, 0, 0.04); cornerSubPix (gray, points[0], subPixWinSize, Size (-1, -1), termcrit); addRemovePt = false; } else if (!points[0].empty ()) { vector<uchar> status; vector<float> err; if (prevGray.empty ()) gray.copyTo (prevGray); calcOpticalFlowPyrLK (prevGray, gray, points[0], points[1], status, err); //, winSize,3, termcrit, 0, 0.001); size_t i, k; for (i = k = 0; i < points[1].size (); i++) { if (!status[i]) continue; points[1][k++] = points[1][i]; if (points->size() > i) { line (image, points[1][i], points[0][i], Scalar(255, 255, 255), 2); } circle (image, points[1][i], 2, Scalar (0, 0, 0), -1, 8); } points[1].resize (k); } if (addRemovePt && points[1].size () < (size_t)MAX_COUNT) { vector<Point2f> tmp; tmp.push_back (point); cornerSubPix (gray, tmp, winSize, cvSize (-1, -1), termcrit); points[1].push_back (tmp[0]); addRemovePt = false; } needToInit = false; imshow ("LK Demo", image); if (i == 0) char c = (char)waitKey ();*/ //imwrite (path + "\\img_big\\" + std::to_string (i) + ".bmp", image); //imwrite (path + "\\img_\\" + std::to_string (i) + ".bmp", img); /*char c = (char)waitKey (0); if (c == 27) break; switch (c) { case 'r': needToInit = true; break; case 'c': points[0].clear (); points[1].clear (); break;\ case 'n': nightMode = !nightMode; break; case 's': imwrite (path + "\\" + std::to_string (i) + ".bmp", prev_img); }*/ } destroyAllWindows (); return 0; }
void findEyes(cv::Mat frame_gray, cv::Rect face) { cv::Mat faceROI = frame_gray(face); cv::Mat debugFace = faceROI; if (kSmoothFaceImage) { double sigma = kSmoothFaceFactor * face.width; GaussianBlur( faceROI, faceROI, cv::Size( 0, 0 ), sigma); } //-- Find eye regions and draw them int eye_region_width = face.width * (kEyePercentWidth/100.0); int eye_region_height = face.width * (kEyePercentHeight/100.0); int eye_region_top = face.height * (kEyePercentTop/100.0); cv::Rect leftEyeRegion(face.width*(kEyePercentSide/100.0), eye_region_top,eye_region_width,eye_region_height); cv::Rect rightEyeRegion(face.width - eye_region_width - face.width*(kEyePercentSide/100.0), eye_region_top,eye_region_width,eye_region_height); //-- Find Eye Centers leftPupil = findEyeCenter(faceROI,leftEyeRegion,"Left Eye"); rightPupil = findEyeCenter(faceROI,rightEyeRegion,"Right Eye"); // get corner regions cv::Rect leftRightCornerRegion(leftEyeRegion); leftRightCornerRegion.width -= leftPupil.x; leftRightCornerRegion.x += leftPupil.x; leftRightCornerRegion.height /= 2; leftRightCornerRegion.y += leftRightCornerRegion.height / 2; cv::Rect leftLeftCornerRegion(leftEyeRegion); leftLeftCornerRegion.width = leftPupil.x; leftLeftCornerRegion.height /= 2; leftLeftCornerRegion.y += leftLeftCornerRegion.height / 2; cv::Rect rightLeftCornerRegion(rightEyeRegion); rightLeftCornerRegion.width = rightPupil.x; rightLeftCornerRegion.height /= 2; rightLeftCornerRegion.y += rightLeftCornerRegion.height / 2; cv::Rect rightRightCornerRegion(rightEyeRegion); rightRightCornerRegion.width -= rightPupil.x; rightRightCornerRegion.x += rightPupil.x; rightRightCornerRegion.height /= 2; rightRightCornerRegion.y += rightRightCornerRegion.height / 2; rectangle(debugFace,leftRightCornerRegion,200); rectangle(debugFace,leftLeftCornerRegion,200); rectangle(debugFace,rightLeftCornerRegion,200); rectangle(debugFace,rightRightCornerRegion,200); // change eye centers to face coordinates rightPupil.x += rightEyeRegion.x; rightPupil.y += rightEyeRegion.y; leftPupil.x += leftEyeRegion.x; leftPupil.y += leftEyeRegion.y; // draw eye centers circle(debugFace, rightPupil, 3, 1234); circle(debugFace, leftPupil, 3, 1234); //-- Find Eye Corners if (kEnableEyeCorner) { cv::Point2f leftRightCorner = findEyeCorner(faceROI(leftRightCornerRegion), true, false); leftRightCorner.x += leftRightCornerRegion.x; leftRightCorner.y += leftRightCornerRegion.y; cv::Point2f leftLeftCorner = findEyeCorner(faceROI(leftLeftCornerRegion), true, true); leftLeftCorner.x += leftLeftCornerRegion.x; leftLeftCorner.y += leftLeftCornerRegion.y; cv::Point2f rightLeftCorner = findEyeCorner(faceROI(rightLeftCornerRegion), false, true); rightLeftCorner.x += rightLeftCornerRegion.x; rightLeftCorner.y += rightLeftCornerRegion.y; cv::Point2f rightRightCorner = findEyeCorner(faceROI(rightRightCornerRegion), false, false); rightRightCorner.x += rightRightCornerRegion.x; rightRightCorner.y += rightRightCornerRegion.y; circle(faceROI, leftRightCorner, 3, 200); circle(faceROI, leftLeftCorner, 3, 200); circle(faceROI, rightLeftCorner, 3, 200); circle(faceROI, rightRightCorner, 3, 200); } imshow(face_window_name, faceROI); // cv::Rect roi( cv::Point( 0, 0 ), faceROI.size()); // cv::Mat destinationROI = debugImage( roi ); // faceROI.copyTo( destinationROI ); }
/////////////////////////////////////////////////////////////////// // Panel::CannyDetection() // Description: This function is called by DetectEdges() and it // is the Canny edge detection function which does not contain // debugging statements. We run the image through several different // image processing functions to prepare the image before edge // detection. After detection the edges we run Hough lines which // approximates lines of minimum length as specified in // Settings.xml. We find all intersections of the Hough lines // then make a minimum area rectangle around the intersections to // approximate the edges of the panel which we are trying to // measure. From there we use the unit conversion calculated // in DetectFeatures() to find a length and width of the current // panel. We report the length and width with a message box. /////////////////////////////////////////////////////////////////// Mat Panel::CannyDetection(Mat image, bool showImg) { Mat greyImage; cvtColor(image, greyImage, CV_BGR2GRAY); Mat eroded, dilated, thresh, blurredThresh, edges, edgesGray; vector<Vec2f> lines; threshold(greyImage, thresh, m_lowCannyThreshold, 255, THRESH_BINARY); erode(thresh, eroded, Mat()); dilate(eroded, dilated, Mat()); GaussianBlur(thresh, blurredThresh, Size(7, 7), m_sigmaX, m_sigmaY); Canny(blurredThresh, edges, m_cannyLow, m_cannyLow*m_ratio, 3); HoughLines(edges, lines, 1, CV_PI / 180, m_houghLength, 0, 0); cvtColor(edges, edgesGray, CV_GRAY2BGR); for (size_t i = 0; i < lines.size(); i++) { float rho = lines[i][0], theta = lines[i][1]; Point pt1, pt2; double a = cos(theta), b = sin(theta); double x0 = a*rho, y0 = b*rho; pt1.x = cvRound(x0 + 1000 * (-b)); pt1.y = cvRound(y0 + 1000 * (a)); pt2.x = cvRound(x0 - 1000 * (-b)); pt2.y = cvRound(y0 - 1000 * (a)); line(edgesGray, pt1, pt2, Scalar(0, 0, 255), 3, CV_AA); } //////////////////////////////////////////////////////// // Compute the intersection from the lines detected //////////////////////////////////////////////////////// vector<Point2f> intersections; for (size_t i = 0; i < lines.size(); i++) { for (size_t j = 0; j < lines.size(); j++) { Vec2f line1 = lines[i]; Vec2f line2 = lines[j]; if (acceptLinePair(line1, line2, (float)CV_PI / 32)) { Point2f intersection = computeIntersect(line1, line2); if (intersection.x >= 0 && intersection.y >= 0) intersections.push_back(intersection); } } } if (intersections.size() > 0) { vector<Point2f>::iterator i; for (i = intersections.begin(); i != intersections.end(); ++i) { cout << "Intersection is " << i->x << ", " << i->y << endl; circle(image, *i, 2, Scalar(0, 255, 0), 3); } // Find the minimum bounding rectangle RotatedRect rect; Point2f rectPoints[4]; Scalar color = Scalar(255, 0, 0); if (intersections.size() == 4) { // TODO } rect = minAreaRect(intersections); rect.points(rectPoints); int j = 0; for (j; j < 4; j++) line(image, rectPoints[j], rectPoints[(j + 1) % 4], color, 5, 8); float topLength = (float)norm(rectPoints[1] - rectPoints[0]); float botLength = (float)norm(rectPoints[3] - rectPoints[2]); float panelWidthPixels = topLength < botLength ? topLength : botLength; float leftHeight = (float)norm(rectPoints[3] - rectPoints[0]); float rightHeight = (float)norm(rectPoints[2] - rectPoints[1]); float panelHeightPixels = leftHeight < rightHeight ? leftHeight : rightHeight; string dimensionDisplayPixels = "Pixels:\nWidth: " + to_string(panelWidthPixels) + " pixels\nHeight: " + to_string(panelHeightPixels) + " pixels"; // ShowMessage(dimensionDisplayPixels); if (m_conversionRate) { float panelWidthReal = panelWidthPixels / m_conversionRate; float panelHeightReal = panelHeightPixels / m_conversionRate; string dimensionDisplayActual = "Actual:\nWidth: " + to_string(panelWidthReal) + " cm\nHeight: " + to_string(panelHeightReal) + " cm"; ShowMessage(dimensionDisplayActual); } } if (showImg){ namedWindow("Intersections", CV_WINDOW_KEEPRATIO); imshow("Intersections", image); } ///////////////////////////////////////////////////////////// // End of Computing the intersection from the lines detected ///////////////////////////////////////////////////////////// return edges; }