码迷,mamicode.com
首页 > 其他好文 > 详细

cv1.5

时间:2016-04-13 13:24:12      阅读:243      评论:0      收藏:0      [点我收藏+]

标签:


使用均值漂移算法查找物体

技术分享技术分享

#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
#include "Histogram1D.h"

#include <iostream>
#include <vector>


#include "ContentFinder.h"
#include "colorhistogram.h"

int main()
{
  //读取參考图像
  cv::Mat image= cv::imread("f:\\img\\ball.jpg");
  if (!image.data)
    return 0; 

  //定义查找物体
  cv::Mat imageROI= image(cv::Rect(85,200,64,64));
  cv::rectangle(image, cv::Rect(85,200,64,64),cv::Scalar(0,0,255));

  //显示參考图像
  cv::namedWindow("第一张图片,标记篮球位置");
  cv::imshow("第一张图片,标记篮球位置",image);

  //获得色度直方图
  ColorHistogram hc;
  cv::MatND colorhist= hc.getHueHistogram(imageROI);

  //读入目标图像
  image= cv::imread("f:\\img\\ball2.jpg");

  //显示目标图像
  cv::namedWindow("第二张图片");
  cv::imshow("第二张图片",image);

  //将RGB图像图像转换为HSV图像
  cv::Mat hsv;
  cv::cvtColor(image, hsv, CV_BGR2HSV);

  //分离图像通道
  vector<cv::Mat> v;
  cv::split(hsv,v);

  //消除饱和度较低的像素点
  int minSat=65;
  cv::threshold(v[1],v[1],minSat,255,cv::THRESH_BINARY);
  cv::namedWindow("第二张图片消除饱和度较低的像素点");
  cv::imshow("第二张图片消除饱和度较低的像素点",v[1]);

  //进行直方图反投影
  ContentFinder finder;
  finder.setHistogram(colorhist);
  finder.setThreshold(0.3f);
  int ch[1]={0};
  cv::Mat result= finder.find(hsv,0.0f,180.0f,ch,1);

  cv::namedWindow("第二张图片进行直方图反投影");
  cv::imshow("第二张图片进行直方图反投影",result);

  //利用位运算消除低饱和度像素
  cv::bitwise_and(result,v[1],result);
  cv::namedWindow("第二张图片利用位运算进一步消除低饱和度像素点");
  cv::imshow("第二张图片利用位运算进一步消除低饱和度像素点",result);

  // 得到反投影直方图概率图像
  finder.setThreshold(-1.0f);
  result= finder.find(hsv,0.0f,180.0f,ch,1);
  cv::bitwise_and(result,v[1],result);
  cv::namedWindow("第二张图片处理后的二值图像");
  cv::imshow("第二张图片处理后的二值图像",result);

  cv::Rect rect(85,200,64,64);
  cv::rectangle(image, rect, cv::Scalar(0,0,255));

  cv::TermCriteria criteria(cv::TermCriteria::MAX_ITER,10,0.01);
  cout << "均值漂移迭代次数 = " << cv::meanShift(result,rect,criteria) << endl;

  cv::rectangle(image, rect, cv::Scalar(0,255,0));

  //展示结果图
  cv::namedWindow("查找结果,红框为第一幅图中篮球位置,绿框为现位置");
  cv::imshow("查找结果,红框为第一幅图中篮球位置,绿框为现位置",image);

  cv::waitKey();
  return 0;
}

    #if!defined CONTENTFINDER  
    #define CONTENTFINDER  
      
    #include <opencv2/core/core.hpp>  
    #include <opencv2/highgui/highgui.hpp>  
    #include <opencv2/imgproc/imgproc.hpp>  
      
    using namespace cv;  
      
    class ContentFinder  
    {  
    private:  
        float hranges[2];  
        const float* ranges[3];  
        int channels[3];  
        float threshold;  
        Mat histogram;  
    public:  
        ContentFinder():threshold(-1.0f)  
        {  
            //所有通道的范围相同  
            ranges[0] = hranges;  
            ranges[1] = hranges;   
            ranges[2] = hranges;  
        }  
      
        //设置门限参数[0,1]  
        void setThreshold(float t)  
        {  
            threshold = t;  
        }  
      
        //获取门限参数  
        float getThreshold()  
        {  
            return threshold;  
        }  
      
        //设置参考的直方图  
        void setHistogram(const Mat& h)  
        {  
            histogram = h;  
            normalize(histogram,histogram,1.0);  
        }  
      
        //简单的利用反向投影直方图寻找  
        Mat find(const Mat& image)  
        {  
            Mat result;  
            hranges[0] = 0.0;  
            hranges[1] = 255.0;  
            channels[0] = 0;  
            channels[1] = 1;  
            channels[2] = 2;  
      
            calcBackProject(&image,1,channels,histogram,result,ranges,255.0);  
            if (threshold>0.0)  
            {  
                cv::threshold(result, result, 255*threshold, 255, cv::THRESH_BINARY);  
            }  
      
            return result;  
        }  
      
        //复杂的利用反向投影直方图,增加了一些参数  
        Mat find(const Mat &image,float minValue,float maxValue,int *channels,int dim)  
        {  
            Mat result;  
            hranges[0] = minValue;  
            hranges[1] = maxValue;  
            for(int i = 0;i < dim;i++)  
            {  
                this->channels[i] = channels[i];  
            }  
            calcBackProject(&image,1,channels,histogram,result,ranges,255.0);  
            if(threshold >0.0)  
                cv::threshold(result,result, 255*threshold,255,THRESH_BINARY);  
            return result;  
      
        }  
    };  
    #endif  


#if!defined COLORHISTOGRAM  
    #define COLORHISTOGRAM  
      
    #include <opencv2/core/core.hpp>  
    #include <opencv2/imgproc/imgproc.hpp>  
      
    using namespace cv;  
      
    class ColorHistogram  
    {  
    private:  
        int histSize[3];  
        float hranges[2];  
        const float* ranges[3];  
        int channels[3];  
    public:  
      
        //构造函数  
        ColorHistogram()  
        {  
            histSize[0]= histSize[1]= histSize[2]= 256;  
            hranges[0] = 0.0;  
            hranges[1] = 255.0;  
            ranges[0] = hranges;  
            ranges[1] = hranges;  
            ranges[2] = hranges;  
            channels[0] = 0;  
            channels[1] = 1;  
            channels[2] = 2;  
        }  
      
        //计算彩色图像直方图  
        Mat getHistogram(const Mat& image)  
        {  
            Mat hist;  
      
            //BGR直方图  
            hranges[0]= 0.0;      
            hranges[1]= 255.0;  
            channels[0]= 0;   
            channels[1]= 1;   
            channels[2]= 2;   
      
            //计算  
            calcHist(&image,1,channels,Mat(),hist,3,histSize,ranges);  
            return hist;  
        }  
      
        //计算颜色的直方图  
        Mat getHueHistogram(const Mat &image)  
        {  
            Mat hist;  
            Mat hue;  
            //转换到HSV空间  
            cvtColor(image,hue,CV_BGR2HSV);  
      
            //设置1维直方图使用的参数  
            hranges[0] = 0.0;  
            hranges[1] = 180.0;  
            channels[0] = 0;  
            //计算直方图  
            calcHist(&hue,1,channels,Mat(),hist,1,histSize,ranges);  
            return hist;  
      
        }  
      
        //减少颜色  
        Mat colorReduce(const Mat &image,int div = 64)  
        {  
            int n = static_cast<int>(log(static_cast<double>(div))/log(2.0));  
            uchar mask = 0xFF<<n;  
            Mat_<Vec3b>::const_iterator it = image.begin<Vec3b>();  
            Mat_<Vec3b>::const_iterator itend = image.end<Vec3b>();  
            //设置输出图像  
            Mat result(image.rows,image.cols,image.type());  
            Mat_<Vec3b>::iterator itr = result.begin<Vec3b>();  
            for(;it != itend;++it,++itr)  
            {  
                (*itr)[0] = ((*it)[0]&mask) + div/2;  
                (*itr)[1] = ((*it)[1]&mask) + div/2;  
                (*itr)[2] = ((*it)[2]&mask) + div/2;  
            }  
            return result;  
        }  
      
    };  
      
      
    #endif  

#if !defined HISTOGRAM  
#define HISTOGRAM  
  
#include <opencv2/core/core.hpp>  
#include <opencv2/imgproc/imgproc.hpp>  
#include <iostream>  
  
using namespace std;  
using namespace cv;  
  
  
class Histogram1D  
{  
private:  
      
    //直方图的点数  
    int histSize[1];  
    //直方图的范围  
    float hranges[2];  
    //指向该范围的指针  
    const float* ranges[1];  
    //通道  
    int channels[1];  
      
  
public:  
    //构造函数  
    Histogram1D()  
    {  
         histSize[0] = 256;  
         hranges[0] = 0.0;  
         hranges[1] = 255.0;  
         ranges[0] = hranges;  
         channels[0] = 0;  
  
    }  
  
    Mat getHistogram(const Mat &image)  
    {  
        Mat hist;  
        //计算直方图函数  
        //参数为:源图像(序列)地址,输入图像的个数,通道数,掩码,输出结果,直方图维数,每一维的大小,每一维的取值范围  
        calcHist(&image,1,channels,Mat(),hist,1,histSize,ranges);  
        //这个函数虽然有很多参数,但是大多数时候,只会用于灰度图像或者彩色图像  
        //但是,允许通过指明一个多通道图像使用多幅图像  
        //第6个参数指明了直方图的维数  
        return hist;  
    }  
  
    Mat getHistogramImage(const Mat &image)  
    {  
        //首先计算直方图  
        Mat hist = getHistogram(image);  
  
        //获取最大值和最小值  
        double maxVal = 0;  
        double minVal = 0;  
        //minMaxLoc用来获得最大值和最小值,后面两个参数为最小值和最大值的位置,0代表不需要获取  
        minMaxLoc(hist,&minVal,&maxVal,0,0);  
        //展示直方图的画板:底色为白色  
        Mat histImg(histSize[0],histSize[0],CV_8U,Scalar(255));  
  
        //将最高点设为bin总数的90%  
        //int hpt = static_cast<int>(0.9*histSize[0]);  
        int hpt = static_cast<int>(histSize[0]);  
        //为每一个bin画一条线  
        for(int h = 0; h < histSize[0];h++)  
        {  
            float binVal = hist.at<float>(h);  
            int intensity = static_cast<int>(binVal*hpt/maxVal);  
            //int intensity = static_cast<int>(binVal);  
            line(histImg,Point(h,histSize[0]),Point(h,histSize[0]-intensity),Scalar::all(0));  
              
        }  
        return histImg;  
    }  
  
    Mat applyLookUp(const Mat& image,const Mat& lookup)  
    {  
        Mat result;  
        LUT(image,lookup,result);  
        return result;  
    }  
  
  
    Mat strech(const Mat &image,int minValue = 0)  
    {  
        //首先计算直方图  
        Mat hist = getHistogram(image);  
        //左边入口  
        int imin = 0;  
        for(;imin< histSize[0];imin++)  
        {  
            cout<<hist.at<float>(imin)<<endl;  
            if(hist.at<float>(imin) > minValue)  
                break;  
  
        }  
        //右边入口  
        int imax = histSize[0]-1;  
        for(;imax >= 0; imax--)  
        {  
            if(hist.at<float>(imax) > minValue)  
                break;  
        }  
  
        //创建查找表  
        int dim(256);  
        Mat lookup(1,&dim,CV_8U);  
          
        for(int i = 0; i < 256; i++)  
        {  
            if(i < imin)  
            {  
                lookup.at<uchar>(i) = 0;  
            }  
            else if(i > imax)  
            {  
                lookup.at<uchar>(i) = 255;  
            }  
            else  
            {  
                lookup.at<uchar>(i) = static_cast<uchar>(255.0*(i-imin)/(imax-imin)+0.5);  
            }  
        }  
        Mat result;  
        result = applyLookUp(image,lookup);  
        return result;  
  
    }  
    Mat equalize(const Mat &image)  
    {  
        Mat result;  
        equalizeHist(image,result);  
        return result;  
    }  
  
};  
#endif


通过直方图比较检索相似图片

CompareHist(),是比较两个统计直方图的分布,总共有四个方法,被定义如下:

#define CV_COMP_CORREL 0
#define CV_COMP_CHISQR 1
#define CV_COMP_INTERSECT2
#define CV_COMP_BHATTACHARYYA3

而这些方法分别为相关系数,卡方,交集法以及在做常态分布比对的Bhattacharyya距离,这些方法都是用来做统计直方图的相似度比较的方法,而且,都是根据统计学的概念,这边就简单的拿来用灰阶统计直方图来比较,而这部份的比较方式,是由图形的色彩结构来着手,下面就简单的用三种情况来分析它们距离比较的方式

    #include "opencv2/highgui/highgui.hpp"  
    #include "opencv/cv.hpp"  
      
    //画直方图用  
    int HistogramBins = 256;  
    float HistogramRange1[2]={0,255};  
    float *HistogramRange[1]={&HistogramRange1[0]};  
      
    /* 
     * imagefile1: 
     * imagefile2: 
     * method: could be CV_COMP_CHISQR, CV_COMP_BHATTACHARYYA, CV_COMP_CORREL, CV_COMP_INTERSECT 
     */  
    int CompareHist(const char* imagefile1, const char* imagefile2)  
    {  
        IplImage *image1=cvLoadImage(imagefile1, 0);  
        IplImage *image2=cvLoadImage(imagefile2, 0);  
      
        CvHistogram *Histogram1 = cvCreateHist(1, &HistogramBins, CV_HIST_ARRAY,HistogramRange);  
        CvHistogram *Histogram2 = cvCreateHist(1, &HistogramBins, CV_HIST_ARRAY,HistogramRange);  
      
        cvCalcHist(&image1, Histogram1);  
        cvCalcHist(&image2, Histogram2);  
      
        cvNormalizeHist(Histogram1, 1);  
        cvNormalizeHist(Histogram2, 1);  
      
        // CV_COMP_CHISQR,CV_COMP_BHATTACHARYYA这两种都可以用来做直方图的比较,值越小,说明图形越相似  
        printf("CV_COMP_CHISQR : %.4f\n", cvCompareHist(Histogram1, Histogram2, CV_COMP_CHISQR));  
        printf("CV_COMP_BHATTACHARYYA : %.4f\n", cvCompareHist(Histogram1, Histogram2, CV_COMP_BHATTACHARYYA));  
      
      
        // CV_COMP_CORREL, CV_COMP_INTERSECT这两种直方图的比较,值越大,说明图形越相似  
        printf("CV_COMP_CORREL : %.4f\n", cvCompareHist(Histogram1, Histogram2, CV_COMP_CORREL));  
        printf("CV_COMP_INTERSECT : %.4f\n", cvCompareHist(Histogram1, Histogram2, CV_COMP_INTERSECT));  
      
        cvReleaseImage(&image1);  
        cvReleaseImage(&image2);  
        cvReleaseHist(&Histogram1);  
        cvReleaseHist(&Histogram2);  
        return 0;  
    }  
      
    int main(int argc, char* argv[])  
    {  
        CompareHist(argv[1], argv[2]);  
        //CompareHist("d:\\camera.jpg", "d:\\camera1.jpg");  
        system("pause");
        return 0;  
    }  
技术分享

图1


技术分享

图2

技术分享

结果

亮度变换

技术分享

#include "opencv\\cv.h"
#include "opencv\\highgui.h"
/*
src and dst are grayscale, 8-bit images;
Default input value: 
           [low, high] = [0,1]; X-Direction
           [bottom, top] = [0,1]; Y-Direction
           gamma ;
if adjust successfully, return 0, otherwise, return non-zero.
*/
int ImageAdjust(IplImage* src, IplImage* dst, 
    double low, double high,   // X方向:low and high are the intensities of src
    double bottom, double top, // Y方向:mapped to bottom and top of dst
    double gamma )
{
if( low<0 && low>1 && high <0 && high>1&&
bottom<0 && bottom>1 && top<0 && top>1 && low>high)
        return -1;
    double low2 = low*255;
    double high2 = high*255;
    double bottom2 = bottom*255;
    double top2 = top*255;
    double err_in = high2 - low2;
    double err_out = top2 - bottom2;
    int x,y;
    double val;
    // intensity transform
    for( y = 0; y < src->height; y++)
    {
        for (x = 0; x < src->width; x++)
        {
            val = ((uchar*)(src->imageData + src->widthStep*y))[x]; 
            val = pow((val - low2)/err_in, gamma) * err_out + bottom2;
            if(val>255) val=255; if(val<0) val=0; // Make sure src is in the range [low,high]
            ((uchar*)(dst->imageData + dst->widthStep*y))[x] = (uchar) val;
        }
    }
    return 0;
}
int main( int argc, char** argv ) 
{
    IplImage *src = 0, *dst = 0;
    
  src=cvLoadImage("f:\\img\\c2.jpg", 0); // force to gray image
  if(src==0)return 0;
        
    
    cvNamedWindow( "src", 1 );
    cvNamedWindow( "result", 1 );
    
    // Image adjust
    dst = cvCloneImage(src);
    // 输入参数 [0,0.5] 和 [0.5,1], gamma=1
if( ImageAdjust( src, dst, 0, 0.5, 0.5, 1, 1)!=0) return -1;
    
    cvShowImage( "src", src );
    cvShowImage( "result", dst );
    cvWaitKey(0);
    cvDestroyWindow("src");
    cvDestroyWindow("result");
    cvReleaseImage( &src );
    cvReleaseImage( &dst );
    
    return 0;
}

cv1.5

标签:

原文地址:http://blog.csdn.net/q123456789098/article/details/51141457

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!