// Gets the hue/sat/val for areas that we believe are license plate characters // Then uses that to filter the whole image and provide a mask. void ColorFilter::findCharColors() { int MINIMUM_SATURATION = 45; if (this->debug) cout << "ColorFilter::findCharColors" << endl; //charMask.copyTo(this->colorMask); this->colorMask = Mat::zeros(charMask.size(), CV_8U); bitwise_not(this->colorMask, this->colorMask); Mat erodedCharMask(charMask.size(), CV_8U); Mat element = getStructuringElement( 1, Size( 2 + 1, 2+1 ), Point( 1, 1 ) ); erode(charMask, erodedCharMask, element); vector<vector<Point> > contours; vector<Vec4i> hierarchy; findContours(erodedCharMask, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE); vector<float> hMeans, sMeans, vMeans; vector<float> hStdDevs, sStdDevs, vStdDevs; for (int i = 0; i < contours.size(); i++) { if (hierarchy[i][3] != -1) continue; Mat singleCharMask = Mat::zeros(hsv.size(), CV_8U); drawContours(singleCharMask, contours, i, // draw this contour cv::Scalar(255,255,255), // in CV_FILLED, 8, hierarchy ); // get rid of the outline by drawing a 1 pixel width black line drawContours(singleCharMask, contours, i, // draw this contour cv::Scalar(0,0,0), // in 1, 8, hierarchy ); //drawAndWait(&singleCharMask); Scalar mean; Scalar stddev; meanStdDev(hsv, mean, stddev, singleCharMask); if (this->debug) { cout << "ColorFilter " << setw(3) << i << ". Mean: h: " << setw(7) << mean[0] << " s: " << setw(7) <<mean[1] << " v: " << setw(7) << mean[2] << " | Std: h: " << setw(7) <<stddev[0] << " s: " << setw(7) <<stddev[1] << " v: " << stddev[2] << endl; } if (mean[0] == 0 && mean[1] == 0 && mean[2] == 0) continue; hMeans.push_back(mean[0]); sMeans.push_back(mean[1]); vMeans.push_back(mean[2]); hStdDevs.push_back(stddev[0]); sStdDevs.push_back(stddev[1]); vStdDevs.push_back(stddev[2]); } if (hMeans.size() == 0) return; int bestHueIndex = this->getMajorityOpinion(hMeans, .65, 30); int bestSatIndex = this->getMajorityOpinion(sMeans, .65, 35); int bestValIndex = this->getMajorityOpinion(vMeans, .65, 30); if (sMeans[bestSatIndex] < MINIMUM_SATURATION) return; bool doHueFilter = false, doSatFilter = false, doValFilter = false; float hueMin, hueMax; float satMin, satMax; float valMin, valMax; if (this->debug) cout << "ColorFilter Winning indices:" << endl; if (bestHueIndex != -1) { doHueFilter = true; hueMin = hMeans[bestHueIndex] - (2 * hStdDevs[bestHueIndex]); hueMax = hMeans[bestHueIndex] + (2 * hStdDevs[bestHueIndex]); if (abs(hueMin - hueMax) < 20) { hueMin = hMeans[bestHueIndex] - 20; hueMax = hMeans[bestHueIndex] + 20; } if (hueMin < 0) hueMin = 0; if (hueMax > 180) hueMax = 180; if (this->debug) cout << "ColorFilter Hue: " << bestHueIndex << " : " << setw(7) << hMeans[bestHueIndex] << " -- " << hueMin << "-" << hueMax << endl; } if (bestSatIndex != -1) { doSatFilter = true; satMin = sMeans[bestSatIndex] - (2 * sStdDevs[bestSatIndex]); satMax = sMeans[bestSatIndex] + (2 * sStdDevs[bestSatIndex]); if (abs(satMin - satMax) < 20) { satMin = sMeans[bestSatIndex] - 20; satMax = sMeans[bestSatIndex] + 20; } if (satMin < 0) satMin = 0; if (satMax > 255) satMax = 255; if (this->debug) cout << "ColorFilter Sat: " << bestSatIndex << " : " << setw(7) << sMeans[bestSatIndex] << " -- " << satMin << "-" << satMax << endl; } if (bestValIndex != -1) { doValFilter = true; valMin = vMeans[bestValIndex] - (1.5 * vStdDevs[bestValIndex]); valMax = vMeans[bestValIndex] + (1.5 * vStdDevs[bestValIndex]); if (abs(valMin - valMax) < 20) { valMin = vMeans[bestValIndex] - 20; valMax = vMeans[bestValIndex] + 20; } if (valMin < 0) valMin = 0; if (valMax > 255) valMax = 255; if (this->debug) cout << "ColorFilter Val: " << bestValIndex << " : " << setw(7) << vMeans[bestValIndex] << " -- " << valMin << "-" << valMax << endl; } Mat imgDebugHueOnly = Mat::zeros(hsv.size(), hsv.type()); Mat imgDebug = Mat::zeros(hsv.size(), hsv.type()); Mat imgDistanceFromCenter = Mat::zeros(hsv.size(), CV_8U); Mat debugMask = Mat::zeros(hsv.size(), CV_8U); bitwise_not(debugMask, debugMask); for (int row = 0; row < charMask.rows; row++) { for (int col = 0; col < charMask.cols; col++) { int h = (int) hsv.at<Vec3b>(row, col)[0]; int s = (int) hsv.at<Vec3b>(row, col)[1]; int v = (int) hsv.at<Vec3b>(row, col)[2]; bool hPasses = true; bool sPasses = true; bool vPasses = true; int vDistance = abs(v - vMeans[bestValIndex]); imgDebugHueOnly.at<Vec3b>(row, col)[0] = h; imgDebugHueOnly.at<Vec3b>(row, col)[1] = 255; imgDebugHueOnly.at<Vec3b>(row, col)[2] = 255; imgDebug.at<Vec3b>(row, col)[0] = 255; imgDebug.at<Vec3b>(row, col)[1] = 255; imgDebug.at<Vec3b>(row, col)[2] = 255; if (doHueFilter && (h < hueMin || h > hueMax)) { hPasses = false; imgDebug.at<Vec3b>(row, col)[0] = 0; debugMask.at<uchar>(row, col) = 0; } if (doSatFilter && (s < satMin || s > satMax)) { sPasses = false; imgDebug.at<Vec3b>(row, col)[1] = 0; } if (doValFilter && (v < valMin || v > valMax)) { vPasses = false; imgDebug.at<Vec3b>(row, col)[2] = 0; } //if (pixelPasses) // colorMask.at<uchar>(row, col) = 255; //else //imgDebug.at<Vec3b>(row, col)[0] = hPasses & 255; //imgDebug.at<Vec3b>(row, col)[1] = sPasses & 255; //imgDebug.at<Vec3b>(row, col)[2] = vPasses & 255; if ((hPasses) || (hPasses && sPasses))//(hPasses && vPasses) || (sPasses && vPasses) || this->colorMask.at<uchar>(row, col) = 255; else this->colorMask.at<uchar>(row, col) = 0; if ((hPasses && sPasses) || (hPasses && vPasses) || (sPasses && vPasses)) { vDistance = pow(vDistance, 0.9); } else { vDistance = pow(vDistance, 1.1); } if (vDistance > 255) vDistance = 255; imgDistanceFromCenter.at<uchar>(row, col) = vDistance; } } vector<Mat> debugImagesSet; if (this->debug) { debugImagesSet.push_back(addLabel(charMask, "Charecter mask")); //debugImagesSet1.push_back(erodedCharMask); Mat maskCopy(colorMask.size(), colorMask.type()); colorMask.copyTo(maskCopy); debugImagesSet.push_back(addLabel(maskCopy, "color Mask Before")); } Mat bigElement = getStructuringElement( 1, Size( 3 + 1, 3+1 ), Point( 1, 1 ) ); Mat smallElement = getStructuringElement( 1, Size( 1 + 1, 1+1 ), Point( 1, 1 ) ); morphologyEx(this->colorMask, this->colorMask, MORPH_CLOSE, bigElement); //dilate(this->colorMask, this->colorMask, bigElement); Mat combined(charMask.size(), charMask.type()); bitwise_and(charMask, colorMask, combined); if (this->debug) { debugImagesSet.push_back(addLabel(colorMask, "Color Mask After")); debugImagesSet.push_back(addLabel(combined, "Combined")); //displayImage(config, "COLOR filter Mask", colorMask); debugImagesSet.push_back(addLabel(imgDebug, "Color filter Debug")); cvtColor(imgDebugHueOnly, imgDebugHueOnly, CV_HSV2BGR); debugImagesSet.push_back(addLabel(imgDebugHueOnly, "Color Filter Hue")); equalizeHist(imgDistanceFromCenter, imgDistanceFromCenter); debugImagesSet.push_back(addLabel(imgDistanceFromCenter, "COLOR filter Distance")); debugImagesSet.push_back(addLabel(debugMask, "COLOR Hues off")); Mat dashboard = drawImageDashboard(debugImagesSet, imgDebugHueOnly.type(), 3); displayImage(config, "Color Filter Images", dashboard); } }
//Thread d'initialisation void *drawingAndParam(void * arg) { string winParametrage = "Thresholded"; string winDetected = "Parametrages"; char key; drawing = false; onDrawing = true; pthread_mutex_init(&mutexVideo, NULL); #if output_video == ov_remote_ffmpeg int errorcode = avformat_open_input(&pFormatCtx, "tcp://192.168.1.1:5555", NULL, NULL); if (errorcode < 0) { cout << "ERREUR CAMERA DRONE!!!" << errorcode; return 0; } avformat_find_stream_info(pFormatCtx, NULL); av_dump_format(pFormatCtx, 0, "tcp://192.168.1.1:5555", 0); pCodecCtx = pFormatCtx->streams[0]->codec; AVCodec *pCodec = avcodec_find_decoder(pCodecCtx->codec_id); if (pCodec == NULL) { cout << "ERREUR avcodec_find_decoder!!!"; return 0; } if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) { cout << "ERREUR avcodec_open2!!!"; return 0; } //pFrame = av_frame_alloc(); //pFrameBGR = av_frame_alloc(); pFrame = avcodec_alloc_frame(); pFrameBGR = avcodec_alloc_frame(); bufferBGR = (uint8_t*)av_mallocz(avpicture_get_size(PIX_FMT_BGR24, pCodecCtx->width, pCodecCtx->height) * sizeof(uint8_t)); avpicture_fill((AVPicture*)pFrameBGR, bufferBGR, PIX_FMT_BGR24, pCodecCtx->width, pCodecCtx->height); pConvertCtx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_BGR24, SWS_SPLINE, NULL, NULL, NULL); img = cvCreateImage(cvSize(pCodecCtx->width, (pCodecCtx->height == 368) ? 360 : pCodecCtx->height), IPL_DEPTH_8U, 3); if (!img) { cout << "ERREUR PAS D'IMAGE!!!"; return 0; } pthread_t ii; pthread_create(&ii, NULL, getimg, NULL); #else VideoCapture cap(0); //capture video webcam #endif HH=179;LS=1;HS=255;LV=1;HV=255;LH=1; namedWindow(winDetected, CV_WINDOW_NORMAL); Mat frame; setMouseCallback(winDetected, MouseCallBack, NULL); while(true) { if(onDrawing) //Tant que l'utilisateur ne commence pas la sélection! { #if output_video != ov_remote_ffmpeg bool bSuccess = cap.read(frame); // Nouvelle capture if (!bSuccess) { cout << "Impossible de lire le flux video" << endl; break; } #else pthread_mutex_lock(&mutexVideo); memcpy(img->imageData, pFrameBGR->data[0], pCodecCtx->width * ((pCodecCtx->height == 368) ? 360 : pCodecCtx->height) * sizeof(uint8_t) * 3); pthread_mutex_unlock(&mutexVideo); frame = cv::cvarrToMat(img, true); #endif imshow(winDetected, frame); } if(!onDrawing && !drawing) //On affiche en direct la sélection de l'utilisateur { Mat tmpFrame=frame.clone(); rectangle(tmpFrame, rec, CV_RGB(51,156,204),1,8,0); imshow(winDetected, tmpFrame); } if(drawing) //L'utilisateur a fini de sélectionner { //cible Ball(1); namedWindow(winParametrage, CV_WINDOW_NORMAL); setMouseCallback(winDetected, NULL, NULL); rectangle(frame, rec, CV_RGB(51,156,204),2,8,0); imshow(winDetected, frame); Mat selection = frame(rec); Ball.setPicture(selection); while(key != 'q') { //Trackbar pour choix de la couleur createTrackbar("LowH", winParametrage, &LH, 179); //Hue (0 - 179) createTrackbar("HighH", winParametrage, &HH, 179); //Trackbar pour Saturation comparer au blanc createTrackbar("LowS", winParametrage, &LS, 255); //Saturation (0 - 255) createTrackbar("HighS", winParametrage, &HS, 255); //Trackbar pour la lumminosite comparer au noir createTrackbar("LowV", winParametrage, &LV, 255);//Value (0 - 255) createTrackbar("HighV", winParametrage, &HV, 255); Mat imgHSV; cvtColor(selection, imgHSV, COLOR_BGR2HSV); //Passe de BGR a HSV Mat imgDetection; inRange(imgHSV, Scalar(LH, LS, LV), Scalar(HH, HS, HV), imgDetection); //Met en noir les parties non comprises dans l'intervalle de la couleur choisie par l'utilisateur //Retire les bruits erode(imgDetection, imgDetection, getStructuringElement(MORPH_ELLIPSE, Size(5, 5))); dilate(imgDetection, imgDetection, getStructuringElement(MORPH_ELLIPSE, Size(5, 5))); dilate(imgDetection, imgDetection, getStructuringElement(MORPH_ELLIPSE, Size(5, 5))); erode(imgDetection, imgDetection, getStructuringElement(MORPH_ELLIPSE, Size(5, 5))); imshow(winParametrage, imgDetection); //Calcul de la "distance" à la cible. On s'en sert comme seuil. Moments position; position = moments(imgDetection); Ball.lastdZone = position.m00; key = waitKey(10); } //Extraction des points d'intérêts de la sélection de l'utilisateur Mat graySelect; int minHessian = 800; cvtColor(selection, graySelect, COLOR_BGR2GRAY); Ptr<SURF> detector = SURF::create(minHessian); vector<KeyPoint> KP; detector->detect(graySelect, KP); Mat KPimg; drawKeypoints(graySelect, KP, KPimg, Scalar::all(-1), DrawMatchesFlags::DEFAULT); Mat desc; Ptr<SURF> extractor = SURF::create(); extractor->compute(graySelect, KP, desc); Ball.setimgGray(graySelect); Ball.setKP(KP); Ball.setDesc(desc); break; } key = waitKey(10); } //Fin de l'initiatlisation on ferme toutes les fenêtres et on passe au tracking destroyAllWindows(); #if output_video != ov_remote_ffmpeg cap.release(); #endif }
int main (int argc, char *argv[]) { struct parms parms; struct timeval start; int i, rank, size, ncy, cyc; int freq[5]={PHI,P,V,C}; double *data, *phi0, *kr, *r, *dr, *phit, *dphi; double telp, time, tcyc, havg, vavg, delh; char *wkdir=0; char input[64]={"init/input.dat"}; char phichek[64]={"init/phi.chk"}; //char phii[Nimob][64]; //for (i = 0; i < Nimob; i++){ // sprintf(phii[i],"data/phi%d.",(i+1)); //} char phii[64] = {"data/phi."}; char p[64] = {"data/p."}; char vx[64] = {"data/vx."}; char vy[64] = {"data/vy."}; char vz[64] = {"data/vz."}; char c[64] = {"data/c."}; char avname[64]={"data/avg."}; char fname[64]; FILE *fileptr; if (argc > 1) cyc = atoi(argv[1]); if (argc > 2) wkdir = argv[2]; winit(&start); // MPI Initialization MPI_Init(&argc,&argv); MPI_Comm_size(MPI_COMM_WORLD, &size); MPI_Comm_rank(MPI_COMM_WORLD, &rank); parms.rank = rank; parms.size = size; parms.V0 = 0; parms.nsten = (2*Dim)+1; parms.Nvar = Dim + 3; nameinput(fname, input, wkdir); fileptr = fopen(fname, "r"); // Read input data fscanf(fileptr, "%*s %*s %*s %*s %*s %*s %*s"); fscanf(fileptr, "%d %lf %lf %lf %lf %lf %lf", &ncy, &parms.Re, &parms.Pe, &parms.Da, &parms.pow, &parms.dx, &parms.dt); fclose(fileptr); // Reading the initial porosity profile #ifdef SEED char phseed[64] = {"init/phi.dat-seed"}; filename(fname, phseed, wkdir, parms); #endif #ifndef SEED char phinit[64] = {"init/phi.dat"}; filename(fname, phinit, wkdir, parms); #endif fileptr = fopen(fname, "r"); fscanf(fileptr, "%5d %5d %5d %5d %5d %5d %lf", &parms.Nx, &parms.Ny, &parms.nx, &parms.ny, &parms.Nz, &parms.cyc, &parms.t); fclose(fileptr); // 2D Domain decomposition parms = mapping(parms); parms.N = (parms.nx*parms.ny*parms.Nz); // Initialize pointers phi0 = (double *) calloc(parms.N, sizeof(double)); data = (double *) calloc(parms.N*parms.Nvar, sizeof(double)); dphi = (double *) calloc(parms.N, sizeof(double)); phit = (double *) calloc(parms.N, sizeof(double)); kr = (double *) calloc(parms.N, sizeof(double)); r = (double *) calloc(parms.N, sizeof(double)); dr = (double *) calloc(parms.N, sizeof(double)); // Create Spiral indexing int *sp = spiral(parms); readf(fname, phi0, parms); // Read from the input porosity profile writedata(phi0, data, 0, 0, parms); // Write the input porosity to pointer "data" @ 0 for(i = 0; i < parms.N; i++){ data[(i*parms.Nvar)+Dim+2] = 1.0; // Initialize c = 1.0 kr[i] = 1.0; } erode(data, kr, r, dr, sp, parms); // Intial fields parms.V0 = avgf(data, 2, parms); if (cyc > 0){ parms.cyc = cyc; filename(fname, phichek, wkdir, parms); readb(fname, phi0, parms); } writedata(phi0, data, 0, 0, parms); // Write the input porosity to pointer "data" @ 0 telp = wtime(&start); time = telp; if (parms.rank == 0){ fprintf(stdout, "Initialization; elapsed time: % .3e\n\n", telp); } while (parms.cyc <= ncy){ erode(data, kr, r, dr, sp, parms); havg = avgf(data, 0, parms); vavg = avgf(data, 2, parms); vavg = vavg*parms.Ny; delh = havg - parms.havg; parms.havg = havg; if (parms.rank == 0){ filename(fname, avname, wkdir, parms); fileptr = fopen(fname, "w"); if (parms.cyc == 0) fprintf(fileptr, " cycle time havg qavg delh\n"); fprintf(fileptr, "%5d % .3e % .3e % .3e % .3e\n", parms.cyc, parms.t, havg, vavg, delh); fclose(fileptr); } //for (i = 0; i < Nimob; i++){ // filename(fname, phii[i], wkdir, parms); // Write data files // writef(fname, data, i, parms, freq[0]); //} filename(fname, phii, wkdir, parms); // Write data files writef(fname, data, 0, parms, freq[0]); filename(fname, p, wkdir, parms); writef(fname, data, 1, parms, freq[1]); filename(fname, vx, wkdir, parms); writef(fname, data, 2, parms, freq[2]); filename(fname, vy, wkdir, parms); writef(fname, data, 3, parms, freq[2]); filename(fname, vz, wkdir, parms); writef(fname, data, 4, parms, freq[2]); filename(fname, c, wkdir, parms); writef(fname, data, Dim+2, parms, freq[3]); // Calculate erosion during dt double dt = parms.dt/parms.Da; #ifdef EULER for (i = 0; i < parms.N; i++) dphi[i] = r[i]*dt; #endif #ifdef MIDPT for (i = 0; i < parms.N; i++){ phit[i] = phi0[i] + 0.5*r[i]*dt; } writedata(phit, data, 0, 0, parms); erode (data, kr, r, dr, sp, parms); for (i = 0; i < parms.N; i++) dphi[i] = r[i]*dt; #endif #ifdef RK4 for (i = 0; i < parms.N; i++){ phit[i] = phi0[i] + 0.5*r[i]*dt; dphi[i] = r[i]*dt/6.0; } writedata(phit, data, 0, 0, parms); erode (data, kr, r, dr, sp, parms); for (i = 0; i < parms.N; i++){ phit[i] = phi0[i] + 0.5*r[i]*dt; dphi[i]+= r[i]*dt/3.0; } writedata(phit, data, 0, 0, parms); erode (data, kr, r, dr, sp, parms); for (i = 0; i < parms.N; i++){ phit[i] = phi0[i] + r[i]*dt; dphi[i]+= r[i]*dt/3.0; } writedata(phit, data, 0, 0, parms); erode (data, kr, r, dr, sp, parms); for (i = 0; i < parms.N; i++) dphi[i]+= r[i]*dt/6.0; #endif // Update height profile for (i = 0; i < parms.N; i++){ phi0[i] += dphi[i]; #ifdef APLIM if (phi0[i] >= AMAX){ phi0[i] = AMAX; kr[i] = 0.0; } #endif } writedata(phi0, data, 0, 0, parms); telp = wtime(&start); tcyc = time; time += telp; tcyc = time - tcyc; if (parms.rank == 0){ fprintf(stdout, "Cycle %6d; cycle time: % .3e total time: % .3e\n\n", parms.cyc, tcyc, time); } parms.cyc++; parms.t += parms.dt; #if CHEK > 0 if ((parms.cyc-1)%CHEK == 0){ filename(fname, phichek, wkdir, parms); writeb(fname, data, 0, parms); /* Checkpoint aperture */ } #endif } // Free memory free(phit); free(r); free(dr); free(kr); free (dphi); free(phi0); free(data); free(sp); // Finalize MPI MPI_Finalize(); return (0); }
std::vector<std::vector<std::vector<cv::Point>>> MultiContourObjectDetector::findApproxContours( cv::Mat image, bool performOpening, bool findBaseShape) { // CREATE ACTIVE ZONE 80% AND 50% --------------------- Point centre(image.size().width / 2, image.size().height / 2); int deleteHeight = image.size().height * _deleteFocus; int deleteWidth = image.size().width * _deleteFocus; int deleteX = centre.x - deleteWidth / 2; int deleteY = centre.y - deleteHeight / 2; int attenuationHeight = image.size().height * _attenuationFocus; int attenuationWidth = image.size().width * _attenuationFocus; int attenuationX = centre.x - attenuationWidth / 2; int attenuationY = centre.y - attenuationHeight / 2; Rect erase(deleteX, deleteY, deleteWidth, deleteHeight); _deleteRect = erase; Rect ease(attenuationX, attenuationY, attenuationWidth, attenuationHeight); _attenuationRect = ease; // ---------------------------------------- bool imageTooBig = false; Mat newImage; if (image.size().height <= 400 || image.size().width <= 400) { Mat pickColor = image(Rect((image.size().width / 2) - 1, image.size().height - 2, 2, 2)); Scalar color = mean(pickColor); int increment = 2; newImage = Mat(Size(image.size().width + increment, image.size().height + increment), image.type()); newImage = color; Point nc(newImage.size().width / 2, newImage.size().height / 2); int incH = image.size().height; int incW = image.size().width; int incX = nc.x - incW / 2; int incY = nc.y - incH / 2; image.copyTo(newImage(Rect(incX, incY, incW, incH))); } else { imageTooBig = true; newImage = image; } Size imgSize = newImage.size(); Mat gray(imgSize, CV_8UC1); Mat thresh(imgSize, CV_8UC1); if (newImage.channels() >= 3) cvtColor(newImage, gray, CV_BGR2GRAY); else newImage.copyTo(gray); int minThreshold; if (performOpening) { // PERFORM OPENING (Erosion --> Dilation) int erosion_size = 3; int dilation_size = 3; if (imageTooBig) { erosion_size = 5; dilation_size = 5; } Mat element = getStructuringElement(0, Size(2 * erosion_size, 2 * erosion_size), Point(erosion_size, erosion_size)); erode(gray, gray, element); dilate(gray, gray, element); minThreshold = mean(gray)[0]; if (minThreshold < 90) minThreshold = 60; else if (minThreshold >= 90 && minThreshold < 125) minThreshold = 100; } threshold(gray, thresh, minThreshold, 255, THRESH_BINARY); #ifdef DEBUG_MODE imshow("Threshold", thresh); #endif vector<vector<Point>> contours; vector<Vec4i> hierarchy; vector<Point> hull, approx; map<int, vector<vector<Point>>> hierachedContours; map<int, vector<vector<Point>>> approxHContours; findContours(thresh, contours, hierarchy, CV_RETR_TREE, CHAIN_APPROX_NONE); #ifdef DEBUG_MODE Mat tempI(image.size(), CV_8UC1); tempI = Scalar(0); drawContours(tempI, contours, -1, cv::Scalar(255), 1, CV_AA); imshow("Contours", tempI); #endif vector<vector<Point>> temp; // CATALOG BY HIERARCHY LOOP for (int i = 0; i < contours.size(); i++) { #ifdef DEBUG_MODE tempI = Scalar(0); temp.clear(); temp.push_back(contours[i]); drawContours(tempI, temp, -1, cv::Scalar(255), 1, CV_AA); #endif int parent = hierarchy[i][3]; if (parent == -1) { if (hierachedContours.count(i) == 0) { // me not found hierachedContours.insert(pair<int, vector<vector<Point>>>(i, vector<vector<Point>>())); hierachedContours[i].push_back(contours[i]); } else { // me found continue; } } else { if (hierachedContours.count(parent) == 0) { // dad not found hierachedContours.insert(pair<int, vector<vector<Point>>>(parent, vector<vector<Point>>())); hierachedContours[parent].push_back(contours[parent]); } hierachedContours[parent].push_back(contours[i]); } } int minPoint, maxPoint; minPoint = _minContourPoints - _minContourPoints / 2.1; maxPoint = _minContourPoints + _minContourPoints / 1.5; // APPROX LOOP for (map<int, vector<vector<Point>>>::iterator it = hierachedContours.begin(); it != hierachedContours.end(); it++) { if (it->second[0].size() < 400) continue; #ifdef DEBUG_MODE tempI = Scalar(0); drawContours(tempI, it->second, -1, cv::Scalar(255), 1, CV_AA); #endif if (it == hierachedContours.begin() && it->second.size() < _aspectedContours) continue; for (int k = 0; k < it->second.size(); k++) { if (it->second[k].size() < _minContourPoints) { if (k == 0) // padre break; else // figlio continue; } convexHull(it->second[k], hull, false); double epsilon = it->second[k].size() * 0.003; approxPolyDP(it->second[k], approx, epsilon, true); #ifdef DEBUG_MODE tempI = Scalar(0); vector<vector<Point>> temp; temp.push_back(approx); drawContours(tempI, temp, -1, cv::Scalar(255), 1, CV_AA); #endif // REMOVE TOO EXTERNAL SHAPES ------------- if (imageTooBig) { Rect bounding = boundingRect(it->second[k]); #ifdef DEBUG_MODE rectangle(tempI, _deleteRect, Scalar(255)); rectangle(tempI, bounding, Scalar(255)); #endif bool isInternal = bounding.x > _deleteRect.x && bounding.y > _deleteRect.y && bounding.x + bounding.width < _deleteRect.x + _deleteRect.width && bounding.y + bounding.height < _deleteRect.y + _deleteRect.height; if (!isInternal) { if (k == 0) break; } } // -------------------------------------------------- if (!findBaseShape) { if (hull.size() < minPoint || hull.size() > maxPoint) { if (k == 0) // padre break; else // figlio continue; } } if (k == 0) { approxHContours.insert(pair<int, vector<vector<Point>>>(it->first, vector<vector<Point>>())); approxHContours.at(it->first).push_back(approx); } else { approxHContours[it->first].push_back(approx); } } } int maxSize = 0, maxID = 0; vector<vector<vector<Point>>> lookupVector; for (map<int, vector<vector<Point>>>::iterator it = approxHContours.begin(); it != approxHContours.end(); it++) { if (it->second.size() <= 1) continue; if (findBaseShape) { int totSize = 0; for (int k = 0; k < it->second.size(); k++) { totSize += it->second[k].size(); } if (totSize > maxSize) { maxSize = totSize; maxID = it->first; } } else { lookupVector.push_back(it->second); } } if (findBaseShape) { lookupVector.push_back(approxHContours.at(maxID)); } return lookupVector; }
void SAGMMBuilder::Update(InputArray frame, OutputArray mask) { Mat Image = frame.getMat(); Mat Foreground(Image.size(),CV_8U,Scalar::all(0)); Mat FilteredImage; // Initialize temporal-spatial filter. if (frame_counter < filter->getTemporalWindow()) { if (frame_counter == 0) { // Initialize in zero three channels of img kernel. filter->initializeFirstImage(Image); } //Apply filter and puts result in FilteredImage. //Note this filter also keeps internal copy of filter result. filter->SpatioTemporalPreprocessing(Image, FilteredImage); Foreground.copyTo(mask); frame_counter += 1; if ( frame_counter == filter->getTemporalWindow() ) { // Initialize model model->initializeModel(FilteredImage); model->getBackground(Background); } return; } //Applies spatial and temporal filter //note this filter return a Mat CV_32FC3 type. filter->SpatioTemporalPreprocessing(Image, FilteredImage); //Global illumination changing factor 'g' between reference image ir and current image ic. double globalIlluminationFactor = factor->getIlluminationFactor(FilteredImage,Background); //Calling background subtraction algorithm. model->operator()(FilteredImage, Foreground, update_bg_model ? -1 : 0, globalIlluminationFactor); // background to calculate illumination next iteration. model->getBackground(Background); // Applying morphological filter, Erode the image Mat Eroded; if (ApplyMorphologicalFilter) { Mat Element(2,2,CV_8U,Scalar(1)); //erode(Mask,Eroded,Mat()); erode(Foreground,Eroded,Element); Eroded.copyTo(mask); } else { // return mask Foreground.copyTo(mask); } Foreground.copyTo(mask); frame_counter += 1; }
void OCV::erodeAndDilate(Mat &frame){ erode(frame, frame, morphERODE, Point(-1,-1), ERODE_DILATE_ITS); dilate(frame, frame, morphDILATE, Point(-1,-1), ERODE_DILATE_ITS); //TODO maybe a blur filter is faster than this... medianBLur? }
void open(int h,int w,int win){ erode(h,w,win); dilate(h,w,win); }
void paperRegistration::detectFigures(cv::vector<cv::vector<cv::Point>>& squares, cv::vector<cv::vector<cv::Point>>& triangles, float minLength, float maxLength, int tresh_binary) { if (currentDeviceImg.empty()) return; //cv::Mat image = currentDeviceImg; //cv::Mat image = cv::imread("C:/Users/sophie/Desktop/meinz.png", CV_LOAD_IMAGE_GRAYSCALE);// cv::imread(path, CV_LOAD_IMAGE_GRAYSCALE); //resize(image, image, cv::Size(500,700)); squares.clear(); triangles.clear(); cv::Mat gray; cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(7,7)); cv::vector<cv::vector<cv::Point> > contours; //compute binary image //use dilatation and erosion to improve edges threshold(currentDeviceImg, gray, tresh_binary, 255, cv::THRESH_BINARY_INV); dilate(gray, gray, element, cv::Point(-1,-1)); erode(gray, gray, element, cv::Point(-1,-1)); // find contours and store them all as a list cv::findContours(gray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); //test each contour cv::vector<cv::Point> approx; cv::vector<cv::vector<cv::Point> >::iterator iterEnd = contours.end(); for(cv::vector<cv::vector<cv::Point> >::iterator iter = contours.begin(); iter != iterEnd; ++iter) { // approximate contour with accuracy proportional // to the contour perimeter cv::approxPolyDP(*iter, approx, arcLength(*iter, true)*0.03, true); //contours should be convex if (isContourConvex(approx)) { // square contours should have 4 vertices after approximation and // relatively large length (to filter out noisy contours) if( approx.size() == 4) { bool rectangular = true; for( int j = 3; j < 6; j++ ) { // if cosines of all angles are small // (all angles are ~90 degree) then write // vertices to result if (fabs(90 - fabs(computeAngle(approx[j%4], approx[j-3], approx[j-2]))) > 7) { rectangular = false; break; } } if (!rectangular) continue; float side1 = computeLength(approx[0], approx[1]); float side2 = computeLength(approx[1], approx[2]); if (side1 > minLength && side1 < maxLength && side2 > minLength && side2 < maxLength) squares.push_back(approx); } // triangle contours should have 3 vertices after approximation and // relatively large length (to filter out noisy contours) else if ( approx.size() == 3) { float side1 = computeLength(approx[0], approx[1]); float side2 = computeLength(approx[1], approx[2]); float side3 = computeLength(approx[2], approx[0]); if (side1 > minLength && side1 < maxLength && side2 > minLength && side2 < maxLength && side3 > minLength && side3 < maxLength) triangles.push_back(approx); } } } }
// display function should be good enough void OpenRadar::DrawRadarData() { int usualColor[15] = {16777215,255,128,65280,32768, 16711680,16711935,8421376,65535,32896 }; /*<usual color*/ CvPoint pt1, pt2; cvZero(RadarImage); cvCircle(RadarImage, cvPoint(DisplayDx,DisplayDy),3, CV_RGB(0,255,255), -1, 8,0); int x,y; unsigned char * pPixel = 0; int colorIndex = 0, colorRGB; int R = 255, G = 0, B = 0; for (int i = 0; i < RadarDataCnt;i++) { if (RadarRho[i] < 0) { //change color colorRGB = usualColor[colorIndex]; R = colorRGB/65536; G = (colorRGB%65536)/256; B = colorRGB%256; colorIndex = (colorIndex + 1)%10; } else { x = (int)(RadarRho[i]*cos(RadarTheta[i])/DisplayRatio) + DisplayDx; y = (int)(-RadarRho[i]*sin(RadarTheta[i])/DisplayRatio)+ DisplayDy; if (x >= 0 && x < RadarImageWdith && y >= 0 && y < RadarImageHeight) { pPixel = (unsigned char*)RadarImage->imageData + y*RadarImage->widthStep + 3*x; pPixel[0] = B; pPixel[1] = G; pPixel[2] = R; } } } pt1.x = DisplayDx; pt1.y = DisplayDy; pt2.x = DisplayDx+line_length*v_scale*sin(v_angle + 0.5*M_PI); pt2.y = DisplayDy+line_length*v_scale*cos(v_angle + 0.5*M_PI); cvLine(RadarImage, pt1, pt2, CV_RGB(255,255,255),2,8,0); pt2.x = DisplayDx+line_length*cos(-(-120 + skip_bin_idx * polarH_resolution)* M_PI/180 ); pt2.y = DisplayDy+line_length*sin(-(-120 + skip_bin_idx * polarH_resolution)* M_PI/180 ); cvLine(RadarImage, pt1, pt2, CV_RGB(0,255,0),1,8,0); pt2.x = DisplayDx+line_length*cos(-(-120 + (polarH_length-skip_bin_idx) * polarH_resolution)* M_PI/180 ); pt2.y = DisplayDy+line_length*sin(-(-120 + (polarH_length-skip_bin_idx) * polarH_resolution)* M_PI/180 ); //pt2.x = DisplayDx+line_length*cos(0.25*M_PI); //pt2.y = DisplayDy+line_length*sin(0.25*M_PI); //cout<< line_length <<endl; //cout<< pt1.x <<" , " << pt1.y <<endl; //cout<< pt2.x <<" , " << pt2.y <<endl; cvLine(RadarImage, pt1, pt2, CV_RGB(0,255,0),1,8,0); float angle; int line_length2; for (int i=0; i<polarH_length;i++) { angle = (-30+i*polarH_resolution)*M_PI/180; line_length2 = H[i]/10; pt2.x = DisplayDx+line_length2*sin(angle); pt2.y = DisplayDy+line_length2*cos(angle); cvCircle(RadarImage, pt2, 2, CV_RGB(255,255,255),1,8,0); } //////////////////////////////////////////////////////////////////////////////////// // mine //////////////////////////////////////////////////////////////////////////////////// Mat binImg = Mat::zeros(RadarImageHeight,RadarImageWdith,CV_8UC1); vector< Point> centerRaw; centerRaw.clear(); for (int i = 0; i < RadarDataCnt;i++) { if (RadarRho[i] > 200) { x = (int)(RadarRho[i]*cos(RadarTheta[i])/DisplayRatio) + DisplayDx; y = (int)(-RadarRho[i]*sin(RadarTheta[i])/DisplayRatio)+ DisplayDy; //centerRaw.push_back(Point(x,y)); //cout<<"P:" <<centerRaw[i].x<<","<<centerRaw[i].y<<endl; if (x >= 0 && x < RadarImageWdith && y >= 0 && y < RadarImageHeight) { circle( binImg,Point(x,y),1,Scalar(255),-1); } } } imshow("binImg",binImg); Mat element = getStructuringElement(MORPH_RECT, Size(1,2)); Mat element2 = getStructuringElement(MORPH_RECT, Size(10,10)); erode(binImg, binImg, element); morphologyEx(binImg, binImg, MORPH_OPEN, element); dilate(binImg, binImg, element2); morphologyEx(binImg, binImg, MORPH_CLOSE, element2); imshow("dilate",binImg); vector< vector<Point> > contours; vector< vector<Point> > filterContours; vector< Vec4i > hierarchy; vector< Point2f> center; vector< float > radius; vector<Point2f> realPoint; findContours(binImg, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE); center.resize(contours.size()); radius.resize(contours.size()); //realPoint.resize(contours.size()); for(int i = 0; i< contours.size(); i++) { minEnclosingCircle(Mat(contours[i]),center[i],radius[i]);//对轮廓进行多变形逼近 circle(binImg,center[i],650/DisplayRatio,Scalar(255),1); //cout<<"No."<<i<<" | P: "<< center[i].x<<","<<center[i].y<<endl; float realX = (center[i].x - DisplayDx) * DisplayRatio; float realY = (center[i].y - DisplayDy) * DisplayRatio; realPoint.push_back(Point2f(realX,realY)); //cout<<"No."<<i<<" | P: "<< realPoint[i].x<<","<<realPoint[i].y<<endl; } imshow("findContours",binImg); // colar map Mat mapImg = Mat::zeros(RadarImageHeight,RadarImageWdith,CV_8UC3); circle(mapImg, Point(DisplayDx,DisplayDy),3, CV_RGB(255,255,255),-1); line(mapImg, Point(DisplayDx,DisplayDy), Point(DisplayDx+40,DisplayDy), Scalar(0,0,255),1); line(mapImg, Point(DisplayDx,DisplayDy), Point(DisplayDx,DisplayDy+40), Scalar(0,255,0),1); for(int i = 0; i< center.size(); i++) { circle(mapImg,center[i],650/DisplayRatio,Scalar(255,255,0),1,CV_AA); circle(mapImg,center[i],100/DisplayRatio,Scalar(0,255,255),-1); } imshow("Map",mapImg); //////////////////////////////////// ukftest::laserPoint msg; vector <float> xvec; vector <float> yvec; for(int i = 0 ; i < realPoint.size(); i++) { // cm xvec.push_back(realPoint[i].x/10.0f); yvec.push_back(realPoint[i].y/10.0f); } // msg msg.header.stamp = ros::Time::now(); msg.header.frame_id = "hokuyo_laser"; msg.x =xvec; msg.y =yvec; if(realPoint.size() >0) msg.isBlocking = 1; else msg.isBlocking = 0; pub_xy. publish(msg); }
void close(int h,int w,int win){ dilate(h,w,win); erode(h,w,win); }
void OpenniFilter::cloud_cb_ (const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr &cloud) { if (!viewer.wasStopped()) { if (cloud->isOrganized()) { // initialize all the Mats to store intermediate steps int cloudHeight = cloud->height; int cloudWidth = cloud->width; rgbFrame = Mat(cloudHeight, cloudWidth, CV_8UC3); drawing = Mat(cloudHeight, cloudWidth, CV_8UC3, NULL); grayFrame = Mat(cloudHeight, cloudWidth, CV_8UC1, NULL); hsvFrame = Mat(cloudHeight, cloudWidth, CV_8UC3, NULL); contourMask = Mat(cloudHeight, cloudWidth, CV_8UC1, NULL); if (!cloud->empty()) { for (int h = 0; h < rgbFrame.rows; h ++) { for (int w = 0; w < rgbFrame.cols; w++) { pcl::PointXYZRGBA point = cloud->at(w, cloudHeight-h-1); Eigen::Vector3i rgb = point.getRGBVector3i(); rgbFrame.at<Vec3b>(h,w)[0] = rgb[2]; rgbFrame.at<Vec3b>(h,w)[1] = rgb[1]; rgbFrame.at<Vec3b>(h,w)[2] = rgb[0]; } } // do the filtering int xPos = 0; int yPos = 0; mtx.lock(); xPos = mouse_x; yPos = mouse_y; mtx.unlock(); // color filtering based on what is chosen by users cvtColor(rgbFrame, hsvFrame, CV_RGB2HSV); Vec3b pixel = hsvFrame.at<Vec3b>(xPos,yPos); int hueLow = pixel[0] < iHueDev ? pixel[0] : pixel[0] - iHueDev; int hueHigh = pixel[0] > 255 - iHueDev ? pixel[0] : pixel[0] + iHueDev; // inRange(hsvFrame, Scalar(hueLow, pixel[1]-20, pixel[2]-20), Scalar(hueHigh, pixel[1]+20, pixel[2]+20), grayFrame); inRange(hsvFrame, Scalar(hueLow, iLowS, iLowV), Scalar(hueHigh, iHighS, iHighV), grayFrame); // removes small objects from the foreground by morphological opening erode(grayFrame, grayFrame, getStructuringElement(MORPH_ELLIPSE, Size(5,5))); dilate(grayFrame, grayFrame, getStructuringElement(MORPH_ELLIPSE, Size(5,5))); // morphological closing (removes small holes from the foreground) dilate(grayFrame, grayFrame, getStructuringElement(MORPH_ELLIPSE, Size(5,5))); erode(grayFrame, grayFrame, getStructuringElement(MORPH_ELLIPSE, Size(5,5))); // gets contour from the grayFrame and keeps the largest contour Mat cannyOutput; vector<vector<Point> > contours; vector<Vec4i> hierarchy; int thresh = 100; Canny(grayFrame, cannyOutput, thresh, thresh * 2, 3); findContours(cannyOutput, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0)); int largestContourArea, largestContourIndex = 0; int defaultContourArea = 1000; // 1000 seems to work find in most cases... cannot prove this vector<vector<Point> > newContours; for (int i = 0; i < contours.size(); i++) { double area = contourArea(contours[i], false); if (area > defaultContourArea) newContours.push_back(contours[i]); } // draws the largest contour: drawing = Mat::zeros(cannyOutput.size(), CV_8UC3); for (int i = 0; i < newContours.size(); i++) drawContours(drawing, newContours, i, Scalar(255, 255, 255), CV_FILLED, 8, hierarchy, 0, Point()); // gets the filter by setting everything within the contour to be 1. inRange(drawing, Scalar(1, 1, 1), Scalar(255, 255, 255), contourMask); // filters the point cloud based on contourMask // again go through the point cloud and filter out unnecessary points pcl::PointCloud<pcl::PointXYZRGBA>::Ptr resultCloud (new pcl::PointCloud<pcl::PointXYZRGBA>); pcl::PointXYZRGBA newPoint; for (int h = 0; h < contourMask.rows; h ++) { for (int w = 0; w < contourMask.cols; w++) { if (contourMask.at<uchar>(h,w) > 0) { newPoint = cloud->at(w,h); resultCloud->push_back(newPoint); } } } if (xPos == 0 && yPos == 0) viewer.showCloud(cloud); else viewer.showCloud(resultCloud); imshow("tracker", rgbFrame); imshow("filtered result", contourMask); char key = waitKey(1); if (key == 27) { interface->stop(); return; } } else cout << "Warning: Point Cloud is empty" << endl; } else cout << "Warning: Point Cloud is not organized" << endl; } }
void KinectController::updateAnalisys(ofxKinect & kinect, float bbX, float bbY, float bbZ, float bbW, float bbH, float bbD){ if(kinect.isFrameNew()){ static int counter = 0; int w = 640; int h = 480; #if ANGLE_FROM_ACCEL //ofVec3f worldOffset(worldX,worldY,worldZ); ofMatrix4x4 m = camTransform.getModelViewMatrix(); int i = 0; for(int y = 0; y < h; y +=step) { for(int x = 0; x < w; x +=step) { const short & distance = kinect.getRawDepthPixelsRef()[x+y*w]; //if(distance > 0) { const ofVec3f & v = kinect.getWorldCoordinateAt(x, y, distance); /*if(correctAngle){ v = v*m; } if(!applyBB || insideBB3D(v,ofVec3f(bbX,bbY,bbZ), ofVec3f(bbW, bbH, bbD))){*/ mesh.getVertices()[i] = v; /*}else{ mesh.getVertices()[i].set(0,0,0); }*/ //} i++; } } #elif ANGLE_FROM_PCL_GROUND_PLANE pcl::PointCloud<pcl::PointXYZ>::Ptr pcPtr = pcl::PointCloud<pcl::PointXYZ>::Ptr(new pcl::PointCloud<pcl::PointXYZ>); for(int y = 0; y < h; y += step) { for(int x = 0; x < w; x += step) { //if(kinect.getDistanceAt(x, y) > 0) { float z = kinect.getDistanceAt(x, y); pcPtr->push_back(pcl::PointXYZ(x,y,z)); //} } } pcPtr->width=640; pcPtr->height=480; pcl::ModelCoefficients::Ptr planeCoeffs = fitPlane<pcl::PointXYZ>(pcPtr,10,5); plane.set(planeCoeffs->values[0],planeCoeffs->values[1],planeCoeffs->values[2],planeCoeffs->values[3]); for(int i=0;i<pcPtr->points.size();i++){ ofVec3f v(pcPtr->points[i].x,pcPtr->points[i].y,pcPtr->points[i].z); if(plane.distanceToPoint(v)>60) mesh.addVertex( kinect.getWorldCoordinateAt(v.x, v.y, v.z) ); } //pcPtr = findAndSubtractPlane<pcl::PointXYZ>(pcPtr,60,5); //ofxPCL::toOf(pcPtr,mesh,1,1,1); #elif CV_ANALISYS cv::Mat backgroundMat = toCv(background); if(captureBg>0){ backgroundMat += toCv(kinect.getDistancePixelsRef()); captureBg--; }else if(captureBg==0){ backgroundMat /= 10; cv::GaussianBlur(backgroundMat,backgroundMat,Size(11,11),10); captureBg=-1; }else{ // difference threshold cv::Mat diffMat = toCv(diff); cv::Mat currentMat = toCv(kinect.getDistancePixelsRef()); cv::Mat gaussCurrentMat = toCv(gaussCurrent); cv::GaussianBlur(currentMat,gaussCurrentMat,Size(11,11),10); cv::absdiff(backgroundMat, gaussCurrentMat, diffMat); //diffMat = toCv(background) - toCv(kinect.getDistancePixelsRef()); threshold(diff,thresPix,.001); thres8Bit = thresPix; cv::Mat kernel; cv::Mat thresMat = toCv(thres8Bit); cv::Point anchor(-1,-1); erode(toCv(thres8Bit),thresMat,kernel,anchor,10); dilate(toCv(thres8Bit),thresMat,kernel,anchor,5); cv::Mat fgMat = toCv(fg); bgSubstractor(toCv(thres8Bit),fgMat); contourFinder.findContours(fg); for(int i=0;i<oscContours.size();i++){ oscContours[i]->newFrame(frame); } polylines = contourFinder.getPolylines(); for(int i=0;i<(int)polylines.size();i++){ ofPoint centroid = polylines[i].getCentroid2D(); polylines[i] = polylines[i].getResampledByCount(16); float z = kinect.getDistanceAt(centroid); for(int j=0;j<oscContours.size();j++){ oscContours[j]->sendBlob(polylines[i],z); } } frame++; if(recording){ //convertColor(kinect.getDepthPixelsRef(),rgbDepth,CV_GRAY2RGB); recorder.addFrame(kinect.getRawDepthPixelsRef()); } } #endif } }
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 *opencv(void * args) { /* DEBUT TRAITEMENT OPENCV */ Mat imgHSV; cvtColor(imgOriginal, imgHSV, COLOR_BGR2HSV); //Passe de BGR a HSV inRange(imgHSV, Scalar(LH, LS, LV), Scalar(HH, HS, HV), imgDetection); //Met en noir les parties non comprit dans notre intervalle pour la balle //Retire les petits parasite en fond erode(imgDetection, imgDetection, getStructuringElement(MORPH_ELLIPSE, Size(5, 5))); dilate(imgDetection, imgDetection, getStructuringElement(MORPH_ELLIPSE, Size(5, 5))); dilate(imgDetection, imgDetection, getStructuringElement(MORPH_ELLIPSE, Size(5, 5))); erode(imgDetection, imgDetection, getStructuringElement(MORPH_ELLIPSE, Size(5, 5))); int i, nlabels; Rect box; int maxArea=0; Mat labels; Mat centroids; Mat stats; //Calcul des différentes composantes connexes de l'image nlabels=connectedComponentsWithStats(imgDetection, labels, stats, centroids, 4, CV_32S); //On recherche la composante connexe la plus grande for(i=1; i<(int)nlabels;i++) { int *row = (int *) &stats.at<int>(i,0); //printf("i : %d, mon area %d vs %d max \n", i, row[CC_STAT_AREA], maxArea); if(row[CC_STAT_AREA]>maxArea) { box = Rect(row[CC_STAT_LEFT], row[CC_STAT_TOP], row[CC_STAT_WIDTH], row[CC_STAT_HEIGHT]); maxArea=row[CC_STAT_AREA]; } } Moments position; //cout << maxArea << endl << (int)(Ball.lastdZone*0.3) << endl; //Si la composante connexe n'est pas assez grande ce n'est pas l'objet if(maxArea>200)//(int)(0.3*Ball.lastdZone)) { Ball.setFoundCV(true); rectangle(imgOriginal, box, Scalar(0,255,0), 4, 8, 0); //Calcule l emplacement de l objet position = moments(imgDetection(box)); double y = position.m01; //y double x = position.m10; //x double dZone = position.m00; //z //cout << "dZone " << dZone << endl << "LdZone " << Ball.lastdZone << endl; posX = x / dZone; posY = y / dZone; posX+=box.x; posY+=box.y; int posZ=0; if(dZone>Ball.lastdZone+Ball.lastdZone*0.2) { posZ=-1; //Trop près de l'objet, il faut reculer. } else if(dZone > Ball.lastdZone-Ball.lastdZone*0.2 && dZone < Ball.lastdZone+Ball.lastdZone*0.2) { posZ=0; //On est à distance correcte de l'objet } else { posZ=1; //Trop loin de l'objet, il faut avancer. } Ball.setCurrentCV((float)posX/fSize.width*100,(float)posY/fSize.height*100, (float)posZ); } else { if(activate) {//On passe ici quand la zone détectée est trop petite ou que l'on en détecte pas. //AtCmd::sendMovement(0, 0, 0, 0, 0); // CHANGE } Ball.setFoundCV(false); } /* FIN TRAITEMENT OPENCV */ return NULL; }
int getPegthresholdFromUser(IplImage *img, Gui *gui, string message, int pegThreshVal, Rect r, cv::Mat &fgMaskPeg) { cv::Mat element[1]; int count = 0; element[0] = getStructuringElement(MORPH_ELLIPSE, Size(8, 8), Point(0, 0)); window_name = gui->windowName(); cvDestroyWindow(window_name.c_str()); cvNamedWindow(window_name.c_str(), CV_WINDOW_AUTOSIZE); cvMoveWindow(window_name.c_str(), 100, 100); img0 = (IplImage *)cvClone(img); char TrackbarName[50]; sprintf(TrackbarName, "thresh x %d", slider_max); slider_val = pegThreshVal; createTrackbar(TrackbarName, window_name, &slider_val, slider_max, 0); Mat src, im1, im3; src = Mat(img0); im1 = Mat::zeros(src.size(), src.type()); cvtColor(src, im3, CV_BGR2HSV); vector<vector<Point> > pegsI; while (1) { pegsI.clear(); Mat channel[3]; split(im3, channel); //Mat fgMaskRing; inRange(channel[2], slider_val, 255, fgMaskPeg); // ROI for (int y = 0; y < fgMaskPeg.rows; y++) { for (int x = 0; x < fgMaskPeg.cols; x++) { if (!(x >= r.tl().x && x <= r.br().x && y >= r.tl().y && y <= r.br().y)) { fgMaskPeg.at<uchar>(Point(x, y)) = 0; } } } erode(fgMaskPeg, fgMaskPeg, element[0]); dilate(fgMaskPeg, fgMaskPeg, element[0]); erode(fgMaskPeg, fgMaskPeg, element[0]); dilate(fgMaskPeg, fgMaskPeg, element[0]); //p.copyTo(p, fgMaskPeg); for (int y = 0; y < src.rows; y++) { for (int x = 0; x < src.cols; x++) { if (fgMaskPeg.at<uchar>(Point(x, y))) { im1.at<Vec3b>(Point(x, y)) = src.at<Vec3b>(Point(x, y)); } else { im1.at<Vec3b>(Point(x, y)) = Vec3b(0,0,0); } } } Mat mask = fgMaskPeg.clone(); vector<Vec4i> hierarchy_ring; //imshow("Initial mask", initial_ring_mask); findContours(mask, pegsI, hierarchy_ring, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0)); count = pegsI.size(); cout << "count Pegs->" << count << endl; cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, 0.5, 0.5, 0, 1, 8); putText(im1, message.c_str(), cvPoint(0, 60), CV_FONT_HERSHEY_SIMPLEX, .7, Scalar(255, 255, 0), 1); imshow(window_name.c_str(), im1); char key = cvWaitKey(40); if ((key == '\r' || key == '\n' || key == '\r\n')) { if (count == 12) { break; } } count = 0; } cvReleaseImage(&img0); return slider_val; }
int main(int argc, char *argv[]) { // Début compteur clock_t d_start, d_stop; d_start = clock(); ImageGS *car = NULL; if(argc > 2) { string arg(argv[1]); if(arg.compare("-pgm") == 0) car = new ImageGS(argv[2]); else if(arg.compare("-ppm") == 0) car = new ImageGS(ImageRGB(argv[2])); else std::cout << "Usage: " << argv[0] << " [-ppm|-pgm] FILE\n"; } else { car = new ImageGS("../data/991211-001"); //car = new ImageGS(ImageRGB("../data/0003")); //car = new ImageGS("../data/99122-2"); } // mesure de la variance (indicatif) #ifdef _DEBUG_ std::cout << "Variance de l'image : " << car->computeVariance() << std::endl; #endif #ifdef GAUSS_PRE_FILTER // filtrage gaussien ImageGS in(*car); in.gaussianFilter(0.5f); in.writePGM("0_gauss_filter"); #else ImageGS in = *car; #endif /* Calcule du gradient en x */ ImageGS *grad = in.computeHorizontalGradient(); grad->recal(); #ifdef _DEBUG_ grad->writePGM("0_grad"); #endif /* Projection horizontal */ float* vect; vect = grad->computeHorizontalProjection(); #ifdef _DEBUG_ writeVect(vect, grad->getHeight(), "data_h_brut.dat"); #endif // Filtre gaussien sur le vecteur de projection gaussianFilter(vect, grad->getHeight(), 6, 0.05f, 1); #ifdef _DEBUG_ writeVect(vect, grad->getHeight(), "data_h_filter.dat"); #endif /* Seuillage 'vertical' on ne garde que les ligne qui on une projection supérieur a un seuil */ // averaging float avg = 0.f; for (unsigned i = 0; i < grad->getHeight(); ++i) avg += vect[i]; avg /= grad->getHeight(); // seuillage vertical for (unsigned i = 0; i < grad->getHeight(); ++i) { // si la projection de cette ligne est sous le seuil on la supprime if( vect[i] < PROJ_HORIZONTAL*avg ) { for (unsigned j = 0; j < grad->getWidth(); ++j) { (*grad)(i, j) = 0.f; } } } delete[] vect; // free #ifdef _DEBUG_ grad->writePGM("1_vertical_filter"); #endif #if 0 /* Projection verticale */ vect = grad->computeVerticalProjection(); #ifdef _DEBUG_ writeVect(vect, grad->getWidth(), "data_v_brut.dat"); #endif // Filtrage gaussien gaussianFilter(vect, grad->getWidth(), 6, 0.05f, 0); #ifdef _DEBUG_ writeVect(vect, grad->getWidth(), "data_v_filter.dat"); #endif /* Seuillage 'vertical' on ne garde que les ligne qui on une projection supérieur a T */ // averaging avg = 0.f; for (unsigned i = 0; i < grad->getWidth(); ++i) avg += vect[i]; avg /= grad->getWidth(); // seuillage horizontal for (unsigned j = 0; j < grad->getWidth(); ++j) { // si la projection de cette ligne est sous le seuil on la supprime if( vect[j] < PROJ_VERTICAL*avg ) { for (unsigned i = 0; i < grad->getHeight(); ++i) { (*grad)(i, j) = 0.f; } } } delete[] vect; // free #ifdef _DEBUG_ grad->writePGM("1_horizontal_filter"); #endif #endif /* binarisation par seuillage global */ grad->thresholdingSmart(T_BIN); #ifdef _DEBUG_ grad->writePGM("2_bin_filter"); #endif /* Opération morphologique pour éliminer le bruit, etc..*/ int width, height; float** mask; #if 1 // Fermeture width=20; height=3; mask = new float*[height]; for (int i = 0; i < height; ++i) { mask[i] = new float[width]; for (int j = 0; j < width; ++j) mask[i][j] = 255.f; } grad->closing(mask, width, height); #ifdef _DEBUG_ grad->writePGM("3_2_close_grad"); #endif #endif #if 1 // Ouverture width=1; height=5; mask = new float*[height]; for (int i = 0; i < height; ++i) { mask[i] = new float[width]; for (int j = 0; j < width; ++j) mask[i][j] = 255.f; } grad->opening(mask, width, height); #ifdef _DEBUG_ grad->writePGM("4_open_grad"); #endif #endif // On applique les rectangle sur l'image de base pour visualiser // les zone detectées comme potentiellement des plaques d'immatriculation ImageRGB *car_detect = new ImageRGB(*car); std::vector<int*> *listPlate = foundConnectedComponents(*grad, car_detect, RATIO_MIN, RATIO_MAX, WIDTH_MIN, WIDTH_MAX, HEIGHT_MIN, HEIGHT_MAX); #ifdef _DEBUG_ car_detect->writePPM("5_plate_detect"); #endif delete grad; // free // On construit la liste des (potentiels) plaque extraites de l'image std::cout << "\n>> Analyse des zone retenues\n"; std::vector<ImageGS*> *listImgPlate = new std::vector<ImageGS*>(); char filename[100]; // Chaine de caractère pour la sauvergarde des images for (unsigned n = 0; n < listPlate->size(); ++n) { // on fixe si possible une marge de quelques pixel (pour eviter le crop) int x1 = max((*listPlate)[n][0]-MARGIN_W, 0), y1 = max((*listPlate)[n][1]-MARGIN_H, 0), x2 = min((*listPlate)[n][2]+MARGIN_W, (int)car->getWidth()), y2 = min((*listPlate)[n][3]+MARGIN_H, (int)car->getHeight()); delete[] (*listPlate)[n]; // free unsigned w = x2-x1, h = y2-y1; // On crée la miniature ImageGS *img = new ImageGS(w, h); for (unsigned i = 0; i < h; ++i) for (unsigned j = 0; j < w; ++j) (*img)(i, j) = (*car)(i+y1, j+x1); // On effectué un derniere verification basé sur les edge de la plaque ImageGS *plate = new ImageGS(*img); plate->inverse(); #ifdef _DEBUG_ std::cout << "Variacance: " << plate->computeVariance() << std::endl; #endif // Seuillage automatique plate->thresholdingOstu(); #if 0 width=1; height=3; mask = new float*[height]; for (int i = 0; i < height; ++i) { mask[i] = new float[width]; for (int j = 0; j < width; ++j) mask[i][j] = 255.f; } plate->opening(mask, width, height); #endif /* Erostion / Disatation extraire les contours */ ImageGS erode(*plate); #if 1 width=2; height=2; mask = new float*[height]; for (int i = 0; i < height; ++i) { mask[i] = new float[width]; for (int j = 0; j < width; ++j) mask[i][j] = 255.f; } erode.erosion(mask, width, height); #endif #if 1 width=1; height=3; mask = new float*[height]; for (int i = 0; i < height; ++i) { mask[i] = new float[width]; for (int j = 0; j < width; ++j) mask[i][j] = 255.f; } plate->dilatation(mask, width, height); #endif // on soustrait l'érodé au dilaté pour garder que les contours (*plate) -= erode; #ifdef _DEBUG_ // Save sprintf(filename, "t_plate_%d", n); plate->writePGM(filename); #endif float var=0, var_cpt=0; for (unsigned j = 1; j < w; ++j) { // on compte le nombre de variation var_cpt = 0; if((*plate)(h/3, j) != (*plate)(h/3, j-1)) ++var_cpt; if((*plate)(h/2, j) != (*plate)(h/2, j-1)) ++var_cpt; if((*plate)(h-h/3, j) != (*plate)(h-h/3, j-1)) ++var_cpt; // On pondère le résultat suivant le nombre variations simultanées if(var_cpt == 3) var += 2.f; else if(var_cpt == 2) var += 1.f; else if(var_cpt == 1) var += .5f; } float varRatio = var/(float)(plate->getWidth()+plate->getHeight()); #ifdef _DEBUG_ std::cout << "Variations (seuil 1: "<< T_1_PLATE << " - seuil 2: " << T_2_PLATE << ") - Variations: " << var << " Ratio de variation: " << varRatio << "\n" << std::endl; #endif /* * On Compare d'abord les seuils classiques (variation minimal et maximal) * Puis on regarde si le ratio 'var/taille de la zone' est respecté. * * Si le premier teste n'est pas valide on regarde seulement si le ratio * est suppérieur a un autre seuil. C'est une "sorte" de seuillage par hystéresis. */ if(var > T_1_PLATE && var < T_2_PLATE && varRatio > T_R2_PLATE) listImgPlate->push_back(img); else if(varRatio > T_R1_PLATE) listImgPlate->push_back(img); delete plate; // free } delete listPlate; // Sauvegarde des plaques reconnues for (unsigned n = 0; n < listImgPlate->size(); ++n) { sprintf(filename, "plate_%d", n); (*listImgPlate)[n]->writePGM(filename); sprintf(filename, "display plate_%d.pgm&", n); system(filename); delete (*listImgPlate)[n]; // free } std::cout << "\n>> Programme terminé : " << listImgPlate->size() << " plaques ont/a été reconnue(s).\n"; // free if(car != NULL) { delete listImgPlate; delete car; delete car_detect; delete[] mask; } // Fin compteur d_stop = clock(); double duration = d_stop-d_start; std::cout << "Temps d'éxecution total : " << duration / (double)CLOCKS_PER_SEC << "s\n"; 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); }
void PlaneEstimator :: estimate(RGBDImage& image, Mat1b& plane_points) { // Passing from 3D to the optimizer const cv::Mat3f& normal_image = image.normal(); const cv::Mat1f& distance_image = image.depth(); cv::Mat1b& mask_image = image.depthMaskRef(); cv::Mat1b objfilter; mask_image.copyTo(objfilter); plane_points = image.normal().clone(); plane_points = 0; if (!image.normal().data) { ntk_dbg(0) << "WARNING: you must active the normal filter to get plane estimation!"; return; } double min[dim]; double max[dim]; int i; for (i=0;i<dim;i++) { max[i] = 1000.0; min[i] = -1000.0; } m_solver.Setup(min,max,DifferentialEvolutionSolver::stBest1Exp,0.8,0.75); // Early estimation of plane points projecting the normal values for (int r = 1; r < plane_points.rows-1; ++r) for (int c = 1; c < plane_points.cols-1; ++c) { if (objfilter.data && objfilter(r,c)) { cv::Vec3f normal = normal_image(r,c); double prod = normal.dot(m_ref_plane); if (prod > 0.95) plane_points(r,c) = 255; else plane_points(r,c) = 0; } } // cleaning of the surface very first estimation dilate(plane_points,plane_points,cv::Mat()); erode(plane_points,plane_points,cv::Mat()); //imwrite("plane-initial.png",plane_points); std::vector<Point3f>& g = m_solver.planePointsRef(); g.clear(); for (int r = 1; r < plane_points.rows-1; ++r) for (int c = 1; c < plane_points.cols-1; ++c) { if (plane_points(r,c)) { // possible table member! Point3f p3d = image.calibration()->depth_pose->unprojectFromImage(Point2f(c,r), distance_image(r,c)); g.push_back(p3d); } } // Calculating... m_solver.Solve(max_generations); double *solution = m_solver.Solution(); // Plane normalizer float suma = solution[0] + solution[1] + solution[2] + solution[3] ; for (int i = 0; i < 4; i++) solution[i] = solution[i]/ suma; ntk::Plane plano (solution[0], solution[1], solution[2], solution[3]); //Update RGBD object m_plane.set(solution[0], solution[1], solution[2], solution[3]); // Final estimation of plane points projecting the normal values cv::Vec3f diffevolnormal(solution[0], solution[1], solution[2]); for (int r = 1; r < plane_points.rows-1; ++r) for (int c = 1; c < plane_points.cols-1; ++c) { if (objfilter.data && objfilter(r,c)) { cv::Vec3f normal = normal_image(r,c); double prod = normal.dot(diffevolnormal); if (prod > 0.5) plane_points(r,c) = 255; else plane_points(r,c) = 0; } } // Cleaning of the DE plane-pixels solution dilate(plane_points,plane_points,cv::Mat()); erode(plane_points,plane_points,cv::Mat()); // imwrite("plane-DE.png",plane_points); }
void blurRemoveMinMax_(Mat& src, Mat& dest, const int r) { const Size ksize = Size(2*r+1,2*r+1); if(src.data!=dest.data)src.copyTo(dest); Mat xv; Mat nv; Mat element = Mat::ones(2*r+1,2*r+1,CV_8U); dilate(src,xv,element); erode(src,nv,element); Mat mind; Mat maxd; Mat mask; absdiff(src,nv,mind);//can move to loop absdiff(src,xv,maxd);// min(mind,maxd,mask);// T* n = nv.ptr<T>(0); T* x = xv.ptr<T>(0); T* d = dest.ptr<T>(0); T* nd = mind.ptr<T>(0); T* mk = mask.ptr<T>(0); int remsize = src.size().area(); #if CV_SSE4_1 if(src.depth()==CV_8U) { const int ssesize = src.size().area()/16; remsize = src.size().area()-ssesize*16; for(int i=0;i<ssesize;i++) { __m128i mmk = _mm_load_si128((__m128i*)mk); __m128i mnd = _mm_load_si128((__m128i*)nd); __m128i mmn = _mm_load_si128((__m128i*)n); __m128i mmx = _mm_load_si128((__m128i*)x); __m128i msk = _mm_cmpeq_epi8(mnd,mmk); _mm_store_si128((__m128i*)d,_mm_blendv_epi8(mmx,mmn,msk)); nd+=16; mk+=16; d+=16; n+=16; x+=16; } } else if(src.depth()==CV_16S || src.depth()==CV_16U) { const int ssesize = src.size().area()/8; remsize = src.size().area()-ssesize*8; for(int i=0;i<ssesize;i++) { __m128i mmk = _mm_load_si128((__m128i*)mk); __m128i mnd = _mm_load_si128((__m128i*)nd); __m128i mmn = _mm_load_si128((__m128i*)n); __m128i mmx = _mm_load_si128((__m128i*)x); __m128i msk = _mm_cmpeq_epi16(mnd,mmk); _mm_store_si128((__m128i*)d,_mm_blendv_epi8(mmx,mmn,msk)); nd+=8; mk+=8; d+=8; n+=8; x+=8; } } else if(src.depth()==CV_32F) { const int ssesize = src.size().area()/4; remsize = src.size().area()-ssesize*4; for(int i=0;i<ssesize;i++) { __m128 mmk = _mm_load_ps((float*)mk); __m128 mnd = _mm_load_ps((float*)nd); __m128 mmn = _mm_load_ps((float*)n); __m128 mmx = _mm_load_ps((float*)x); __m128 msk = _mm_cmpeq_ps(mnd,mmk); _mm_store_ps((float*)d,_mm_blendv_ps(mmx,mmn,msk)); nd+=4; mk+=4; d+=4; n+=4; x+=4; } } else if(src.depth()==CV_64F) { const int ssesize = src.size().area()/2; remsize = src.size().area()-ssesize*2; for(int i=0;i<ssesize;i++) { __m128d mmk = _mm_load_pd((double*)mk); __m128d mnd = _mm_load_pd((double*)nd); __m128d mmn = _mm_load_pd((double*)n); __m128d mmx = _mm_load_pd((double*)x); __m128d msk = _mm_cmpeq_pd(mnd,mmk); _mm_store_pd((double*)d,_mm_blendv_pd(mmx,mmn,msk)); nd+=2; mk+=2; d+=2; n+=2; x+=2; } } #endif for(int i=0;i<remsize;i++) { { if(nd[i]==mk[i]) { d[i]=n[i]; } else { d[i]=x[i]; } } } }
void edgeProcessing(Mat src, Mat &dst, Rect roi) { Mat imgGray, imgClone, imgClone_gray; cvtColor(src, imgGray, CV_BGR2GRAY); //cvtColor(imgClone, imgClone_gray, CV_BGR2GRAY); imgClone_gray = imgGray; Mat imgThresh; //adaptiveThreshold(imgClone_gray, imgThresh, 255, CV_ADAPTIVE_THRESH_GAUSSIAN_C, 1, 11, 9); double otsu_thres = threshold(imgClone_gray, imgThresh, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU); double highThresh = otsu_thres; // threshold(grayImage1, grayImage, highThresh*0.2, 255, CV_THRESH_BINARY); cv::Canny(imgGray, imgThresh, highThresh*0.3, highThresh, 3); // imshow("Thresh", imgThresh); Mat img_bin = imgThresh(roi).clone(); vector<vector<Point> > contours; vector<Vec4i> hierarchy; ////CvMemStorage *storage = cvCreateMemStorage(0); ////CvSeq *seq_contour = cvCreateSeq(CV_SEQ_ELTYPE_POINT, sizeof(CvSeq), sizeof(CvPoint), storage); cv::findContours(img_bin, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0)); /// Draw contours int xmax, ymax, xmin, ymin; int xleft, xright, ytop, ybottom; Mat drawing = Mat::zeros(src(roi).size(), CV_8UC3); int width = drawing.cols; int height = drawing.rows; int x=20,y=20; int maxhL=0,imaxL=-1,maxhR=0,imaxR=-1; for (int i = 0; i< contours.size(); i++) { int count = contours[i].size(); if (count>100) { for (int t = 0; t < count; t++) { if (t == 0){ xleft = xright = contours[i][t].x; ytop = ybottom = contours[i][t].y; } if (contours[i][t].x > xright){ xright = contours[i][t].x; } if (contours[i][t].x < xleft) { xleft = contours[i][t].x; } if (contours[i][t].y > ytop) { ytop = contours[i][t].y; } if (contours[i][t].y < ybottom) { ybottom = contours[i][t].y; } xmin = xleft; xmax = xright; ymin = ybottom; ymax = ytop; } int w = xmax - xmin, h = ymax - ymin; int s = w*h; if (((xmax + xmin) / 2)>width / 10 && ((xmax + xmin) / 2) < width *2/ 5 && (ymax + ymin) / 2<height * 3 / 4 && (ymax + ymin) / 2>height / 4 && s>height&&h>height/4) //if () { if (h > maxhL) { maxhL = h; imaxL = i; } } if (((xmax + xmin) / 2)>width / 2 && ((xmax + xmin) / 2) < width && (ymax + ymin) / 2<height * 3 / 4 && (ymax + ymin) / 2>height / 4 && s>height&&h>height / 4) //if () { if (h > maxhR) { maxhR = h; imaxR = i; } } } } Scalar color = Scalar(0, 0, 255); if(imaxL!=-1)drawContours(drawing, contours, imaxL, color, 2, 8, hierarchy, 3, Point()); if (imaxR != -1)drawContours(drawing, contours, imaxR, color, 2, 8, hierarchy, 3, Point()); /// Show in a window // namedWindow("Contours", CV_WINDOW_AUTOSIZE); imshow("Contours", drawing); Mat img_bin_gray; cvtColor(drawing, img_bin_gray, CV_BGR2GRAY); threshold(img_bin_gray, img_bin_gray, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU); int erosion_size = 5; cv::Mat element = cv::getStructuringElement(MORPH_RECT, Size(2 * erosion_size + 1, 2 * erosion_size + 1), Point(erosion_size, erosion_size)); dilate(img_bin_gray, img_bin_gray, element); erode(img_bin_gray, img_bin_gray, element); //imshow("thres2", img_bin_gray); dst = img_bin_gray; }
void pxsnsr(vector<vector<Point>> &contours, Mat &Seg_img_red, Mat &Seg_img_blue) { Rect *r = new Rect[contours.size()]; // 定义外接矩形数组 Mat obj_rec_thr = Mat::zeros(Seg_img_red.size(), CV_8UC3); for (unsigned int i = 0; i < contours.size(); i++) { r[i] = boundingRect(Mat(contours[i]));// boundingRect获取这个外接矩形 } /// 绘出轮廓及其凸包 Mat Seg_img_blue_hull(Seg_img_blue.size(), CV_8U, Scalar(0)); vector<vector<Point> >hull(contours.size()); for (unsigned int i = 0; i< contours.size(); i++) { convexHull(Mat(contours[i]), hull[i], false); fillConvexPoly(Seg_img_blue_hull, &hull[i][0], hull[i].size(), Scalar(1)); } erode(Seg_img_blue_hull, Seg_img_blue_hull, Mat(), Point(-1, -1), dilate_size); // 对图像进行之前的膨胀恢复 Seg_img_blue_hull.convertTo(Seg_img_blue_hull, CV_32F); imshow("Seg_img_blue _hull", Seg_img_blue_hull); double Evaluation = 0; // 对潜在目标的打分值初始化 double Evaluation_max = 0; // 对潜在目标的打分最大值初始化 int index_best = -1; // 最优轮廓标记 <注意此处初始值应为-1> int index = 0; // 轮廓标记 cout << contours.size() << endl; vector<vector<Point>>::const_iterator itContours = contours.begin(); //for (; itContours != contours.end(); ++itContours) while (itContours != contours.end()) { Mat imageROI_red = Seg_img_red(cv::Rect(r[index].x, r[index].y, r[index].width, r[index].height)); Mat imageROI_blue = Seg_img_blue_hull(cv::Rect(r[index].x, r[index].y, r[index].width, r[index].height)); Mat imageROI_red_blue = imageROI_red + imageROI_blue; threshold(imageROI_red_blue, imageROI_red_blue, 1, 1, THRESH_BINARY); // 进行阈值分割(大于阈值1等于2时候取 1) Scalar s1 = sum(imageROI_red_blue); Scalar s2 = sum(imageROI_blue); double sum_red = s1.val[0]; // 获取图像块包含在蓝色中的红色像素数量 double sum_blue = s2.val[0]; // 获取图像块中蓝色像素数量 double pixel_sum_rate = rate(sum_red, sum_blue); // 计算图像块中红蓝像素的比例 cout << "sum_red:" << sum_red << "\t" << "," << "sum_blue:" << sum_blue << "\t"; cout << "pixel_sum_rate:" << pixel_sum_rate << endl; // 将红蓝像素比太低的连通域轮廓删除 if ((pixel_sum_rate < threshold_value_pixel_rate) || (sum_red < 12)) // 如当前轮廓不含一定的红色像素 { itContours = contours.erase(itContours); // 删除当前轮廓 <特别注意:删除当前轮廓后迭代器自动指向后一个> index++; continue; } else // 如当前轮廓含一定的红色像素 { int aaa = contours.size(); // 用于设置条件断点 Evaluation = sum_red; // 目标轮廓简单评价值定义 if (Evaluation > Evaluation_max) { Evaluation_max = Evaluation; index_best++; cout << "index_best - " << index_best << endl; } index++; itContours++; // 继续检索下一个轮廓 <此处必须要代码指定迭代器转向后一个轮廓> } } int ttt = contours.size(); // 用于设置条件断点 // 如果仍然有大于一个潜在目标则选取最优的一个 if (ttt > 1) { int index = 0; vector<vector<Point>>::const_iterator itContours_2 = contours.begin(); while(itContours_2 != contours.end()) { if (index != index_best) itContours_2 = contours.erase(itContours_2); else ++itContours_2; index++; } } delete[] r; }
//========================== // Process Function //========================== void ffos_process_image (unsigned char *data, int w, int h) { int threshold = otsu_i(data, w, h); global_cfg.otsu_threshold = threshold; #ifndef __SOLVER__ printf("otsu threshold: %d\n",threshold); #endif // temporary data after image processing unsigned char * _temp = malloc(w * h * sizeof(unsigned char)); unsigned char * pbuf = malloc(w * h * sizeof(unsigned char)); int erosion_count = global_cfg.erosion_count; memcpy(_temp, data, w * h * sizeof(unsigned char)); binarization(pbuf, data, threshold, w, h); // erosion on the binary image for(int count = 1; count <= erosion_count; count++){ #ifndef __SOLVER__ printf("erosion count = %d\n", count); #endif erode(pbuf, w, h); }// end count // for temporary debug #ifndef __SOLVER__ write_pgm(pbuf, w, h, "erosion.pgm"); #endif int * x_point = malloc(w*sizeof(int)); int * y_point = malloc(h*sizeof(int)); int num_center_x = calculate_x_position(pbuf, x_point, w, h); int num_center_y = calculate_y_position(pbuf, y_point, w, h); global_cfg.num_x = num_center_x; global_cfg.num_y = num_center_y; #ifndef __SOLVER__ draw_bounding_box(_temp, w, h, x_point, y_point, num_center_x, num_center_y); // for temporary debug write_pgm((unsigned char *)_temp, w, h, "BondBox.pgm"); #endif // localize the middle detected oled // firstly, locate the center oled (more complex methods can be used!) // coordinate of the middle led int index_center_x = num_center_x/2; int index_center_y = num_center_y/2; // approximate center of oled int center_x = x_point[index_center_x]; int center_y = y_point[index_center_y]; // decide the bonding box (consider the corner cases) rectangle box = get_bounding_box(center_x, center_y, w, h); int cog_x_i, cog_y_i; center_of_gravity_i(&cog_x_i, &cog_y_i, data, w, &box); global_cfg.cog_x_c = cog_x_i; global_cfg.cog_y_c = cog_y_i; free(x_point); free(y_point); free(pbuf ); free(_temp ); #ifndef __SOLVER__ //Processing finished, print the results printf("==========================\n"); printf("detected x positions = %d \n", num_center_x); printf("detected y positions = %d \n", num_center_y); printf("detected OLED = %d\n", num_center_x * num_center_y); if( (num_center_x == 0) || (num_center_y == 0) ){ printf("WARNING: no OLED detected!!!\n"); } printf("==========================\n"); printf("index_center_x = %d\n", index_center_x); printf("index_center_y = %d\n", index_center_y); printf("num_center_x = %d\n", num_center_x); printf("num_center_y = %d\n", num_center_y); printf("==========================\n"); printf("==========================\n"); printf("Bonding Box of Center OLED\n"); printf("(y_NW ,x_NW) = (%d, %d)\n", box.y_nw, box.x_nw); printf("(y_SE ,x_SE) = (%d, %d)\n", box.y_se, box.x_se); printf("==========================\n"); printf("Calculated (moment) x, y position of the middle OLED\n"); printf("x position of center OLED = %d (INT)\n", cog_x_i); printf("y position of center OLED = %d (INT)\n", cog_y_i); printf("==========================\n"); #endif } // end process_image()
/////////////////////////////////////////////////////////////////// // 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; }