Mat Histogram::drawHist(MatND _histMat) { if(_histMat.channels()>1) cvError(1,__FUNCTION__,"Only for 1D histograms",__FILE__,__LINE__); int w = 400; int h = 400; Mat histImage( h, w, CV_8UC3, Scalar( 0,0,0) ); Mat i2; cv::normalize(_histMat,i2,0,255,CV_MINMAX); for( int i = 0; i < _histSize[0]; i++ ) { int bin_w = cvRound( (double) w/_histSize[0]); rectangle( histImage, Point( i*bin_w, h ), Point( (i+1)*bin_w, h - cvRound( i2.at<float>(i)*h/255.0 ) ), Scalar( 0, 0, 255 ), -1 ); /*line( histImage, Point( bin_w*(i-1), hist_h - cvRound(1*i2.at<float>(i-1)) ) , Point( bin_w*(i), hist_h - cvRound(1*i2.at<float>(i)) ), Scalar( 255, 0, 0), 2, 8, 0 ); /*line( histImage, Point( bin_w*(i-1), hist_h - cvRound(g_hist.at<float>(i-1)) ) , Point( bin_w*(i), hist_h - cvRound(g_hist.at<float>(i)) ), Scalar( 0, 255, 0), 2, 8, 0 ); line( histImage, Point( bin_w*(i-1), hist_h - cvRound(r_hist.at<float>(i-1)) ) , Point( bin_w*(i), hist_h - cvRound(r_hist.at<float>(i)) ), Scalar( 0, 0, 255), 2, 8, 0 );*/ } return histImage; }
void Analyser::compareToHistogram(Mat &image, Mat &histo, Mat &result) { Mat img_blur(image.rows, image.cols, image.type()); GaussianBlur(image, img_blur, Size(0,0), 3); Mat img_hsv(img_blur.rows, img_blur.cols, image.type()); cvtColor(img_blur, img_hsv, CV_BGR2HSV); /// Use only the Hue value Mat hue, saturation, brightness; hue.create( img_hsv.size(), img_hsv.depth() ); saturation.create( img_hsv.size(), img_hsv.depth() ); brightness.create( img_hsv.size(), img_hsv.depth() ); int chH[] = { 0, 0 }; mixChannels( &img_hsv, 1, &hue, 1, chH, 1 ); int chS[] = { 1, 0 }; mixChannels( &img_hsv, 1, &saturation, 1, chS, 1 ); int chB[] = { 2, 0 }; mixChannels( &img_hsv, 1, &brightness, 1, chB, 1 ); Mat planes[] = {hue, saturation}; result = Mat(image.rows, image.cols, CV_8UC1, Scalar(0)); float h_ranges[] = {0,180}; float s_ranges[] = {0,255}; const float* ranges[] = {h_ranges, s_ranges}; MatND backproj; calcBackProject( planes, 2, 0, histo, backproj, ranges, 1, true ); normalize( backproj, backproj, 0, 255, NORM_MINMAX, -1, Mat() ); // On enlève les valeurs trop sombres for (int y=0 ; y<brightness.rows; y++) { for (int x=0 ; x<brightness.cols; x++) { if (brightness.data[brightness.step*y+x] < 50) { backproj.data[backproj.step * y + x ] = 0; } } } backproj.copyTo(result); }
Mat RadialHistogramClassifier::caracteristicVector(const Mat &segmentedHand) { Mat direction = handDirection(segmentedHand).second; float angle = atan(direction.at<float>(0,1)/direction.at<float>(0,0)); Mat rotatedHand; rotateHand(segmentedHand, rotatedHand, angle); Mat flippedHand = rotatedHand; if (detectHandSide(rotatedHand, 1) == LEFT_HAND) { horizontalSymmetry(rotatedHand, flippedHand); } MatND handRadialHistogram; Point2f palmCenter = estimatePalmCenter( flippedHand, this->maxFingerWidth); radialHistogramWithCenter( flippedHand, handRadialHistogram, this->numberOfBins, palmCenter); return handRadialHistogram.t(); }
void CV_ArrayOpTest::run( int /* start_from */) { int errcount = 0; // dense matrix operations { int sz3[] = {5, 10, 15}; MatND A(3, sz3, CV_32F), B(3, sz3, CV_16SC4); CvMatND matA = A, matB = B; RNG rng; rng.fill(A, CV_RAND_UNI, Scalar::all(-10), Scalar::all(10)); rng.fill(B, CV_RAND_UNI, Scalar::all(-10), Scalar::all(10)); int idx0[] = {3,4,5}, idx1[] = {0, 9, 7}; float val0 = 130; Scalar val1(-1000, 30, 3, 8); cvSetRealND(&matA, idx0, val0); cvSetReal3D(&matA, idx1[0], idx1[1], idx1[2], -val0); cvSetND(&matB, idx0, val1); cvSet3D(&matB, idx1[0], idx1[1], idx1[2], -val1); Ptr<CvMatND> matC = cvCloneMatND(&matB); if( A.at<float>(idx0[0], idx0[1], idx0[2]) != val0 || A.at<float>(idx1[0], idx1[1], idx1[2]) != -val0 || cvGetReal3D(&matA, idx0[0], idx0[1], idx0[2]) != val0 || cvGetRealND(&matA, idx1) != -val0 || Scalar(B.at<Vec4s>(idx0[0], idx0[1], idx0[2])) != val1 || Scalar(B.at<Vec4s>(idx1[0], idx1[1], idx1[2])) != -val1 || Scalar(cvGet3D(matC, idx0[0], idx0[1], idx0[2])) != val1 || Scalar(cvGetND(matC, idx1)) != -val1 ) { ts->printf(CvTS::LOG, "one of cvSetReal3D, cvSetRealND, cvSet3D, cvSetND " "or the corresponding *Get* functions is not correct\n"); errcount++; } } RNG rng; const int MAX_DIM = 5, MAX_DIM_SZ = 10; // sparse matrix operations for( int si = 0; si < 10; si++ ) { int depth = (unsigned)rng % 2 == 0 ? CV_32F : CV_64F; int dims = ((unsigned)rng % MAX_DIM) + 1; int i, k, size[MAX_DIM]= {0}, idx[MAX_DIM]= {0}; vector<string> all_idxs; vector<double> all_vals; vector<double> all_vals2; string sidx, min_sidx, max_sidx; double min_val=0, max_val=0; int p = 1; for( k = 0; k < dims; k++ ) { size[k] = ((unsigned)rng % MAX_DIM_SZ) + 1; p *= size[k]; } SparseMat M( dims, size, depth ); map<string, double> M0; int nz0 = (unsigned)rng % max(p/5,10); nz0 = min(max(nz0, 1), p); all_vals.resize(nz0); all_vals2.resize(nz0); Mat_<double> _all_vals(all_vals), _all_vals2(all_vals2); rng.fill(_all_vals, CV_RAND_UNI, Scalar(-1000), Scalar(1000)); if( depth == CV_32F ) { Mat _all_vals_f; _all_vals.convertTo(_all_vals_f, CV_32F); _all_vals_f.convertTo(_all_vals, CV_64F); } _all_vals.convertTo(_all_vals2, _all_vals2.type(), 2); if( depth == CV_32F ) { Mat _all_vals2_f; _all_vals2.convertTo(_all_vals2_f, CV_32F); _all_vals2_f.convertTo(_all_vals2, CV_64F); } minMaxLoc(_all_vals, &min_val, &max_val); double _norm0 = norm(_all_vals, CV_C); double _norm1 = norm(_all_vals, CV_L1); double _norm2 = norm(_all_vals, CV_L2); for( i = 0; i < nz0; i++ ) { for(;;) { for( k = 0; k < dims; k++ ) idx[k] = (unsigned)rng % size[k]; sidx = idx2string(idx, dims); if( M0.count(sidx) == 0 ) break; } all_idxs.push_back(sidx); M0[sidx] = all_vals[i]; if( all_vals[i] == min_val ) min_sidx = sidx; if( all_vals[i] == max_val ) max_sidx = sidx; setValue(M, idx, all_vals[i], rng); double v = getValue(M, idx, rng); if( v != all_vals[i] ) { ts->printf(CvTS::LOG, "%d. immediately after SparseMat[%s]=%.20g the current value is %.20g\n", i, sidx.c_str(), all_vals[i], v); errcount++; break; } } Ptr<CvSparseMat> M2 = (CvSparseMat*)M; MatND Md; M.copyTo(Md); SparseMat M3; SparseMat(Md).convertTo(M3, Md.type(), 2); int nz1 = (int)M.nzcount(), nz2 = (int)M3.nzcount(); double norm0 = norm(M, CV_C); double norm1 = norm(M, CV_L1); double norm2 = norm(M, CV_L2); double eps = depth == CV_32F ? FLT_EPSILON*100 : DBL_EPSILON*1000; if( nz1 != nz0 || nz2 != nz0) { errcount++; ts->printf(CvTS::LOG, "%d: The number of non-zero elements before/after converting to/from dense matrix is not correct: %d/%d (while it should be %d)\n", si, nz1, nz2, nz0 ); break; } if( fabs(norm0 - _norm0) > fabs(_norm0)*eps || fabs(norm1 - _norm1) > fabs(_norm1)*eps || fabs(norm2 - _norm2) > fabs(_norm2)*eps ) { errcount++; ts->printf(CvTS::LOG, "%d: The norms are different: %.20g/%.20g/%.20g vs %.20g/%.20g/%.20g\n", si, norm0, norm1, norm2, _norm0, _norm1, _norm2 ); break; } int n = (unsigned)rng % max(p/5,10); n = min(max(n, 1), p) + nz0; for( i = 0; i < n; i++ ) { double val1, val2, val3, val0; if(i < nz0) { sidx = all_idxs[i]; string2idx(sidx, idx, dims); val0 = all_vals[i]; } else { for( k = 0; k < dims; k++ ) idx[k] = (unsigned)rng % size[k]; sidx = idx2string(idx, dims); val0 = M0[sidx]; } val1 = getValue(M, idx, rng); val2 = getValue(M2, idx); val3 = getValue(M3, idx, rng); if( val1 != val0 || val2 != val0 || fabs(val3 - val0*2) > fabs(val0*2)*FLT_EPSILON ) { errcount++; ts->printf(CvTS::LOG, "SparseMat M[%s] = %g/%g/%g (while it should be %g)\n", sidx.c_str(), val1, val2, val3, val0 ); break; } } for( i = 0; i < n; i++ ) { double val1, val2; if(i < nz0) { sidx = all_idxs[i]; string2idx(sidx, idx, dims); } else { for( k = 0; k < dims; k++ ) idx[k] = (unsigned)rng % size[k]; sidx = idx2string(idx, dims); } eraseValue(M, idx, rng); eraseValue(M2, idx); val1 = getValue(M, idx, rng); val2 = getValue(M2, idx); if( val1 != 0 || val2 != 0 ) { errcount++; ts->printf(CvTS::LOG, "SparseMat: after deleting M[%s], it is =%g/%g (while it should be 0)\n", sidx.c_str(), val1, val2 ); break; } } int nz = (int)M.nzcount(); if( nz != 0 ) { errcount++; ts->printf(CvTS::LOG, "The number of non-zero elements after removing all the elements = %d (while it should be 0)\n", nz ); break; } int idx1[MAX_DIM], idx2[MAX_DIM]; double val1 = 0, val2 = 0; M3 = SparseMat(Md); minMaxLoc(M3, &val1, &val2, idx1, idx2); string s1 = idx2string(idx1, dims), s2 = idx2string(idx2, dims); if( val1 != min_val || val2 != max_val || s1 != min_sidx || s2 != max_sidx ) { errcount++; ts->printf(CvTS::LOG, "%d. Sparse: The value and positions of minimum/maximum elements are different from the reference values and positions:\n\t" "(%g, %g, %s, %s) vs (%g, %g, %s, %s)\n", si, val1, val2, s1.c_str(), s2.c_str(), min_val, max_val, min_sidx.c_str(), max_sidx.c_str()); break; } minMaxLoc(Md, &val1, &val2, idx1, idx2); s1 = idx2string(idx1, dims), s2 = idx2string(idx2, dims); if( (min_val < 0 && (val1 != min_val || s1 != min_sidx)) || (max_val > 0 && (val2 != max_val || s2 != max_sidx)) ) { errcount++; ts->printf(CvTS::LOG, "%d. Dense: The value and positions of minimum/maximum elements are different from the reference values and positions:\n\t" "(%g, %g, %s, %s) vs (%g, %g, %s, %s)\n", si, val1, val2, s1.c_str(), s2.c_str(), min_val, max_val, min_sidx.c_str(), max_sidx.c_str()); break; } } ts->set_failed_test_info(errcount == 0 ? CvTS::OK : CvTS::FAIL_INVALID_OUTPUT); }
void CHumanTracker::generateRegionHistogram(Mat& region, MatND &hist, bool vis) { MatND prior = hist.clone(); Mat hsv; cvtColor(region, hsv, CV_BGR2HSV); Mat mask = Mat::zeros(region.rows, region.cols, CV_8UC1); for (int r = 0; r < region.rows; r++) { for (int c = 0; c < region.cols; c++) { unsigned int v = hsv.at<Vec3b>(r,c)[2]; // TODO: Make me parameters if (( v > 10) && (v < 240)) { mask.at<uchar>(r,c) = 1; } } } // namedWindow( "Face Mask", 1 ); // imshow( "Face Mask", mask * 255 ); int histSize[] = {hbins, sbins}; float hranges[] = {0, 180}; float sranges[] = {0, 256}; const float* ranges[] = { hranges, sranges}; int channels[] = {0, 1}; calcHist(&hsv, 1, channels, mask, hist, 2, histSize, ranges, true, false); for( int h = 0; h < hbins; h++ ) { for( int s = 0; s < sbins; s++ ) { hist.at<float>(h,s) = (0.99 * prior.at<float>(h,s)) + (0.01 * hist.at<float>(h,s)); } } // We should make it a probability dist. normalize(hist, hist, 1.0, 0.0, NORM_L1); if (vis) { // For vis Mat visHist; normalize(hist, visHist, 255.0, 0.00, NORM_MINMAX); int scale = 10; Mat histImg = Mat::zeros(sbins * scale, hbins* scale, CV_8UC3); for( int h = 0; h < hbins; h++ ) { for( int s = 0; s < sbins; s++ ) { float binVal = visHist.at<float>(h, s); int intensity = cvRound(binVal);///maxVal); rectangle( histImg, Point(h*scale, s*scale), Point( (h+1)*scale - 1, (s+1)*scale - 1), Scalar::all(intensity), CV_FILLED ); } } if ((debugLevel & 0x08) == 0x08) { namedWindow( "H-S Histogram", 1 ); imshow( "H-S Histogram", histImg ); waitKey(1); } } }
/* * 功能:直方图相似度计算和匹配 * 参数: * 状态: */ int histMatch() { Mat frame,img; Mat staRoiHist; MatND RoiHist; int DRAW_H=400,DRAW_W=400; Mat draw(DRAW_W,DRAW_H,CV_8UC3,Scalar(0,0,0));//建立一个显示直方图的图片,背景为纯黑色 int DRAW_BIN_W=cvRound(DRAW_W/histsize1); /****打开摄像头****/ VideoCapture cam(0); if(!cam.isOpened()) return -1; /****鼠标捕捉****/ namedWindow("camera",1); namedWindow("rgb_hist",1); setMouseCallback("camera",onMouse,0);//这里用的是面向对象的思想,只要有鼠标动作就会调用鼠标响应函数 while(1) { if(!pause)//暂停按钮只需控制视频的读取 { cam>>frame; if(frame.empty()) break; //break此处跳出的是while语句,一般是跳出for或while语句,不要理解为跳出if语句 } if(tracking) { Mat RoiImage(frame,selectROI); /*********************************************************************************************/ /* calcHist():计算图像块的直方图矩阵 /*calcHist(),第1个参数为原数组区域列表;第二个参数为有计算几个原数组;参数3为需要统计的通道索引数;参数4为操作掩码 /*第5个参数为存放目标直方图矩阵;参数6为需要计算的直方图的维数;参数7为每一维的bin的个数;参数8为每一维数值的取值范围 /*参数10为每个bin的大小是否相同的标志,默认为1,即bin的大小都相同;参数11为直方图建立时清除内存痕迹标志,默认为0,即清除 /**********************************************************************************************/ calcHist(&RoiImage,1,channels,Mat(),RoiHist,3,histsize,ranges); //原数组区域RoiImage,1个源,需要统计的通道索引为{0,1,2}, //目标直方图RoiHist,3维,每一维的bin数histsize,取值范围为 //ranges,实际上计算出的目标矩阵类似一维矩阵。 /****************************************************************************************/ /* normalize():根据某种范数或者数值范围归一化数组 /* normalize(),参数1表示需要归一化的数组;参数2为归一化后的目的数组;参数3表示输出数值的最小值/最大值 /* 或者输出数值的范数;参数4表示输出数值的最小值/最大值;参数5表示归一化数组使用的归一化类型,默认值为使用 /* L2范数;参数6为对应元素的掩膜矩阵,默认值为空,即不采用掩膜操作 /*****************************************************************************************/ normalize(RoiHist,RoiHist);//使用L2范数将RoiHist直方图原地归一化 vector<Mat> rgb_planes;//这里的vector为向量,向量的数据类型为Mat结构体,向量的长度为3 split(RoiImage,rgb_planes);//将rgb图分解到rgb_planes各个分量中 calcHist(&rgb_planes[0],1,0,Mat(),rhist,1,&histsize1,&ranges1); normalize(rhist,rhist,0,DRAW_H,NORM_MINMAX);//进行最大最小值归一化 calcHist(&rgb_planes[1],1,0,Mat(),ghist,1,&histsize1,&ranges1); normalize(ghist,ghist,0,DRAW_H,NORM_MINMAX); calcHist(&rgb_planes[2],1,0,Mat(),bhist,1,&histsize1,&ranges1); normalize(bhist,bhist,0,DRAW_H,NORM_MINMAX); if(nFrame_num==1) { // preselectROI=selectROI; preselectROI.x=selectROI.x; preselectROI.y=selectROI.y; preselectROI.width=selectROI.width; preselectROI.height=selectROI.height; staRoiHist=RoiHist.clone();//第一次选定目标,作为标准模板目标 } else if(nFrame_num>1&&comp==true) { /**************************************************************************************/ /* compareHist():比较2个直方图的相似度 /* compareHist(),参数1为比较相似度的直方图1;参数2为比较相似度的直方图2;参数3为相似度的计算方式。有四种, /* 分别为CV_COMP_CORREL,CV_COMP_CHISQR,CV_COMP_INTERSECT,CV_COMP_BHATTACHARYYA /*************************************************************************************/ double distence=compareHist(staRoiHist,RoiHist,CV_COMP_INTERSECT); //计算后面选定的与这次选定的相似度,使用INTERSECT,值越大越相似 printf("与第1次选定的图像区域相似度为:%f\n",distence);//数组越大,相似度越大 //显示直方图 for(int i=1;i<histsize1;i++) { //画直线中要注意2点,因为图片的原点在左上角,而直方图坐标系的原点在左下角, //所以高度值都需要被直方图图纸高度减掉,另外取一维直方图时只能用at运算符 line(draw,Point(DRAW_BIN_W*(i-1),DRAW_H-cvRound(rhist.at<float>((i-1)))), Point(DRAW_BIN_W*(i),DRAW_H-cvRound(rhist.at<float>(i))),Scalar(255,0,0),2,8,0); line(draw,Point(DRAW_BIN_W*(i-1),DRAW_H-cvRound(ghist.at<float>((i-1)))), Point(DRAW_BIN_W*(i),DRAW_H-cvRound(ghist.at<float>(i))),Scalar(0,255,0),2,8,0); line(draw,Point(DRAW_BIN_W*(i-1),DRAW_H-cvRound(bhist.at<float>((i-1)))), Point(DRAW_BIN_W*(i),DRAW_H-cvRound(bhist.at<float>(i))),Scalar(0,0,255),2,8,0); } imshow("rgb_hist",draw); draw=Mat::zeros(DRAW_W,DRAW_H,CV_8UC3);//每画完一次直方图后都进行一次清0操作 comp=false; } rectangle(frame,selectROI,Scalar(0,255,0),2,8);//手动选定一次就显示一次 }//end tracking rectangle(frame,preselectROI,Scalar(0,0,255),5,8);//初始的选定目标一直不变 imshow("camera",frame); //键盘响应 char c = (char)waitKey(10); if( c == 27 ) break; switch(c) { case 'p'://暂停键 pause = !pause; break; default: ; } }//end while;