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);
        }
	}
}
Example #2
0
/*
 *	功能:直方图相似度计算和匹配
 *  参数:
 *  状态:
 */
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;