zoukankan      html  css  js  c++  java
  • opencv 直方图反向投影

      转载至:http://www.cnblogs.com/zsb517/archive/2012/06/20/2556508.html

    直方图反向投影式通过给定的直方图信息,在图像找到相应的像素分布区域,opencv提供两种算法,一个是基于像素的,一个是基于块的。

    使用方法不写了,可以参考一下几个网站:

    直方图反向投影参考1

    直方图参考2

     

    测试例子1:灰度直方图反向投影

    
    IplImage * image= cvLoadImage("22.jpg");  
    IplImage * image2= cvLoadImage("2.jpg");  
    int hist_size=256;  
    float range[] = {0,255};  
    float* ranges[]={range};  
    
    IplImage* gray_plane = cvCreateImage(cvGetSize(image),8,1);  
    cvCvtColor(image,gray_plane,CV_BGR2GRAY);  
    CvHistogram* gray_hist = cvCreateHist(1,&hist_size,CV_HIST_ARRAY,ranges,1);  
    cvCalcHist(&gray_plane,gray_hist,0,0);  
    //cvNormalizeHist(gray_hist,1.0);  
    
    IplImage* gray_plane2 = cvCreateImage(cvGetSize(image2),8,1);  
    cvCvtColor(image2,gray_plane2,CV_BGR2GRAY);  
    //CvHistogram* gray_hist2 = cvCreateHist(1,&hist_size,CV_HIST_ARRAY,ranges,1);  
    //cvCalcHist(&gray_plane2,gray_hist2,0,0);  
    //cvNormalizeHist(gray_hist2,1.0);  
    IplImage* dst = cvCreateImage(cvGetSize(gray_plane2),IPL_DEPTH_8U,1);  
    
    cvCalcBackProject(&gray_plane2, dst ,gray_hist);
    cvEqualizeHist(dst,dst);
    //产生的图像太暗,做了一些直方图均衡
    
    cvNamedWindow( "dst");  
    cvShowImage("dst",dst);  
    cvNamedWindow( "src");  
    cvShowImage( "src", image2 );  
    cvNamedWindow( "templ");  
    cvShowImage( "templ", image );  
    cvWaitKey();

    效果图:

     2
    第一个图为源图像,中间的那个小图像是产生用于反向投影的直方图的图像,最后的用直方图均衡化后的结果图像,可以看到,苹果的像素位置几被找到了。

    测试例子2:彩色直方图反向投影测试

    
    IplImage*src= cvLoadImage("myhand2.jpg", 1);  
    IplImage*templ=cvLoadImage("myhand3.jpg",1);
    
    cvNamedWindow( "Source" );  
    cvShowImage( "Source", src );  
    
    
    IplImage* h_plane2 = cvCreateImage( cvGetSize(src), 8, 1 );      
    IplImage* s_plane2 = cvCreateImage( cvGetSize(src), 8, 1 );    
    IplImage* v_plane2 = cvCreateImage( cvGetSize(src), 8, 1); 
    IplImage* planes2[] = { h_plane2, s_plane2,v_plane2 };
    
    IplImage* hsv2 = cvCreateImage( cvGetSize(src), 8, 3 );
    cvCvtColor( src, hsv2, CV_BGR2HSV );    
    cvSplit( hsv2, h_plane2, s_plane2, v_plane2, 0 );
    printf("h%d",h_plane2->widthStep);
    printf("s%d",h_plane2->widthStep);
    printf("v%d",h_plane2->widthStep);
    
    IplImage* h_plane = cvCreateImage( cvGetSize(templ), 8, 1 );      
    IplImage* s_plane = cvCreateImage( cvGetSize(templ), 8, 1 );    
    IplImage* v_plane = cvCreateImage( cvGetSize(templ), 8, 1);    
    IplImage* planes[] = { h_plane, s_plane,v_plane };
    IplImage* hsv = cvCreateImage( cvGetSize(templ), 8, 3 );  
    cvCvtColor( templ, hsv, CV_BGR2HSV );    
    cvSplit( hsv, h_plane, s_plane, v_plane, 0 );
    printf("h%d
    ",h_plane->widthStep);
    printf("s%d
    ",s_plane->widthStep);
    printf("v%d
    ",v_plane->widthStep);
    
    int h_bins = 16, s_bins = 16,v_bins=16;
    int hist_size[] = {h_bins, s_bins,v_bins};
    float h_ranges[] = {0,255};
    float s_ranges[] = {0,255};
    float v_ranges[] = {0,255};
    float* ranges[] = { h_ranges, s_ranges,v_ranges};
    CvHistogram* hist;
    hist = cvCreateHist( 3, hist_size, CV_HIST_ARRAY, ranges, 1 ); 
    cvCalcHist( planes, hist, 0, 0 );
    //1.double a=1.f;
    //2.cvNormalizeHist(hist,a);
    //templ's hist is just calculate
    
    IplImage*back_project=cvCreateImage(cvGetSize(src),8,1);//!!归一,把改成,就弹出对话框,说planes的steps不是一致的!
    
    cvZero(back_project);                                  //但是我去掉归一,改成就可以显示
    
    //NOW we begin calculate back project
    
    cvCalcBackProject(planes2,back_project,hist);
    
    
    cvNamedWindow( "back_project" );  
    cvShowImage( "back_project", back_project );  
    
    cvWaitKey(0);

    测试结果:

     QQ截图20120620142552

    手的肤色位置基本找到了,但是有一个问题,在做直方图反向的时候,直方图分级是16等分,并不是256等分,下图是32等分和8等分的图像效果:

    4      32等分 5 8等分

    程序里面使用了SHV分量,也算是肤色检测的一个实例,里面的颜色区分很明显,所有采用大一点的区域统计,能更好的找到肤色的位置,如果采用很细的颜色区分,光照的影响也会考虑进去了。

    测试例子3:基于块的直方图投影

    这种方法速度很慢,模版图像别弄的太大了。

    
    IplImage*src= cvLoadImage("2.jpg", 1);  
    IplImage*templ=cvLoadImage("22.jpg",1);
    
    cvNamedWindow( "Source" );  
    cvShowImage( "Source", src );  
    
    IplImage* h_plane2 = cvCreateImage( cvGetSize(src), 8, 1 );      
    IplImage* s_plane2 = cvCreateImage( cvGetSize(src), 8, 1 );    
    IplImage* v_plane2 = cvCreateImage( cvGetSize(src), 8, 1); 
    IplImage* planes2[] = { h_plane2, s_plane2,v_plane2 };
    
    IplImage* hsv2 = cvCreateImage( cvGetSize(src), 8, 3 );
    cvCvtColor( src, hsv2, CV_BGR2HSV );    
    cvSplit( hsv2, h_plane2, s_plane2, v_plane2, 0 );
    printf("h%d",h_plane2->widthStep);
    printf("s%d",h_plane2->widthStep);
    printf("v%d",h_plane2->widthStep);
    
    IplImage* h_plane = cvCreateImage( cvGetSize(templ), 8, 1 );      
    IplImage* s_plane = cvCreateImage( cvGetSize(templ), 8, 1 );    
    IplImage* v_plane = cvCreateImage( cvGetSize(templ), 8, 1);    
    IplImage* planes[] = { h_plane, s_plane,v_plane };
    IplImage* hsv = cvCreateImage( cvGetSize(templ), 8, 3 );  
    cvCvtColor( templ, hsv, CV_BGR2HSV );    
    cvSplit( hsv, h_plane, s_plane, v_plane, 0 );
    printf("h%d
    ",h_plane->widthStep);
    printf("s%d
    ",s_plane->widthStep);
    printf("v%d
    ",v_plane->widthStep);
    
    int h_bins = 16, s_bins = 16,v_bins=16;
    int hist_size[] = {h_bins, s_bins,v_bins};
    float h_ranges[] = {0,255};
    float s_ranges[] = {0,255};
    float v_ranges[] = {0,255};
    float* ranges[] = { h_ranges, s_ranges,v_ranges};
    CvHistogram* hist;
    hist = cvCreateHist( 3, hist_size, CV_HIST_ARRAY, ranges, 1 ); 
    cvCalcHist( planes, hist, 0, 0 );
    
    CvSize temp ;
    temp.height = src->height - templ->height + 1;
    temp.width  = src->width - templ->width + 1;
    IplImage*back_project=cvCreateImage(temp,IPL_DEPTH_32F,1);//!!归一,把改成,就弹出对话框,说planes的steps不是一致的!
    
    cvZero(back_project);                                     //但是我去掉归一,改成就可以显示
    cvCalcBackProjectPatch(planes2, back_project, cvGetSize(templ), hist,CV_COMP_INTERSECT ,1);
    
    cvNamedWindow( "back_project" );  
    cvShowImage( "back_project", back_project );  
    
    cvWaitKey(0);


    测试图像:

    当模版图像小雨目标的时候,作为区域检测器,测试如下:可以找到手区域

    6

    当模版等于目标的时候,测试如下:输出图像,较亮的部分就是人的头部大致位置

    7

    基于块的反向,速度太慢了。

    
  • 相关阅读:
    洛谷【P1177】【模板】归并排序
    洛谷【P1177】【模板】快速排序
    洛谷【P1104】生日(冒泡排序版)
    洛谷【P1104】生日(插入排序版)
    洛谷【P1104】生日(选择排序版)
    BZOJ5443:[CEOI2018]Lottery
    ReactNative---ref的用法和技巧
    ios---运用MJRefresh组件设置下拉刷新
    ReactNative---setState与性能的平衡
    ios---设置UITabBarController的字体颜色和大小
  • 原文地址:https://www.cnblogs.com/zfluo/p/5131870.html
Copyright © 2011-2022 走看看