OpenCV直方图(1)

来源:互联网 发布:电脑怎么下载淘宝 编辑:程序博客网 时间:2024/06/03 14:52

直方图是一个简单的表格,表示一个图像(有时是一组图像)中具有某个值的像素的数量。因此灰度图图像的直方图有256个项目,也叫箱子(bin)。0号箱子表示值为0的像素的数量。

1、计算图像的直方图
要计算直方图,可以调用cv::calcHist函数,它是通用的直方图计算函数,可处理包含任何类型和范围的多通道图像。
如计算单通道灰度图像:
先创建灰度图像直方图的类:

// To create histograms of gray-level imagesclass Histogram1D {  private:    int histSize[1];         // number of bins in histogram    float hranges[2];        // range of values    const float* ranges[1];  // pointer to the different value ranges    int channels[1];         // channel number to be examined  public:    Histogram1D()    {        // Prepare default arguments for 1D histogram        histSize[0]= 256;   // 256 bins        hranges[0]= 0.0;    // from 0 (inclusive)        hranges[1]= 256.0;  // to 256 (exclusive)        ranges[0]= hranges;         channels[0]= 0;     // we look at channel 0    }// Computes the 1D histogram.    cv::Mat getHistogram(const cv::Mat &image)    {        cv::Mat hist;        // Compute histogram        cv::calcHist(&image,             1,          // histogram of 1 image only            channels,   // the channel used            cv::Mat(),  // no mask is used            hist,       // the resulting histogram            1,          // it is a 1D histogram            histSize,   // number of bins            ranges      // pixel value range        );        return hist;    }     // Computes the 1D histogram and returns an image of it.    cv::Mat getHistogramImage(const cv::Mat &image, int zoom = 1){        // Compute histogram first        cv::Mat hist = getHistogram(image);        // Creates image        return Histogram1D::getImageOfHistogram(hist, zoom);    }  // Create an image representing a histogram    static cv::Mat getImageOfHistogram(const cv::Mat &hist, int zoom) {        // Get min and max bin values        double maxVal = 0;        double minVal = 0;        cv::minMaxLoc(hist, &minVal, &maxVal, 0, 0);        // get histogram size        int histSize = hist.rows;        // Square image on which to display histogram        cv::Mat histImg(histSize*zoom, histSize*zoom, CV_8U, cv::Scalar(255));        // set highest point at 90% of nbins (i.e. image height)        int hpt = static_cast<int>(0.9*histSize);        // Draw vertical line for each bin        for (int h = 0; h < histSize; h++) {            float binVal = hist.at<float>(h);            if (binVal>0) {                int intensity = static_cast<int>(binVal*hpt / maxVal);                cv::line(histImg, cv::Point(h*zoom, histSize*zoom),                    cv::Point(h*zoom, (histSize - intensity)*zoom), cv::Scalar(0), zoom);            }        }        return histImg;    }应用:// The histogram object    Histogram1D h;    // Compute the histogram    cv::Mat histo= h.getHistogram(image);    // Loop over each bin    for (int i=0; i<256; i++)         cout << "Value " << i << " = " << histo.at<float>(i) << endl;      // Display a histogram as an image    cv::namedWindow("Histogram");    cv::imshow("Histogram",h.getHistogramImage(image));

2、查找表
查找表是一对一(或者是多对一)的函数,定义了如何把像素转换成新的值。它是一个一维的数组,对于规则的灰度图像,它包含256个项目。利用查找表的项目i,可得到对应的灰度级的新强度值。

newIntensity=lookup[oldIntensity];

(1)、假设创建一个使图像翻转的查找表:

    // 创建一个图像反转的查找表        int dims[1] = { 256 };        cv::Mat lookup(1, dims, CV_8U);        for (int i = 0; i<256; i++)       {          lookup.at<uchar>(i) = 255-i;        }

OpenCV 的cv::LUT函数在图像上应用查找表,可生成一个新的图像。函数定义:

// Applies a lookup table transforming an input image into a 1-channel image    static cv::Mat applyLookUp(const cv::Mat& image, // input image      const cv::Mat& lookup)   { // 1x256 uchar matrix      // the output image      cv::Mat result;      // apply lookup table      cv::LUT(image,lookup,result);      return result;    }

使用实例:

result=applyLookup(image,lookup);

(2)、使用直方图以提高图像的对比度
定义一个修改原始图像直方图的查找表,可以提高图像的对比度。
图像伸展的方法:

使用:

    // Stretch the image, setting the 1% of pixels at black and 1% at white    cv::Mat str= h.stretch(image,0.01f);

3、直方图均衡化
很多时候,图像的视觉缺陷并不是它使用的强度范围太窄,而是由于部分强度值的使用频率比其他强度值要高很多。一幅高质量的图像,对所有的像素强度都均衡使用。
OpenCV提供equalizeHist函数用于直方图均衡化处理。
cv::equalizeHist(image,result);
处理的规则;p%像素的强度值必须小于或等于255*p%,即强度值i的映像对应强度值小于i的像素所占的百分比。
可以构建查找表:

lookup.at<uchar>(i)=static_cast<uchar>(255*p[i]/image.total());

实现方法:

 // Equalizes the source image.    static cv::Mat equalize(const cv::Mat &image) {        cv::Mat result;        cv::equalizeHist(image,result);        return result;    }

4、反向投影直方图检测特定图像的内容
如果图像的某个区域含有特定的纹理或物体,这个区域的直方图可以看做是一个函数,该函数返回某个像素属于这个特殊纹理或物体的分辨率。
如果想要在某个图像中检测特定的内容,先要选择一个包含所需样本的兴趣区域,然后获取它的直方图,再通过归一化直方图,得到一个函数,由此可得到特定强度的像素属于这个区域的概率。
选择目标区域:

    // Define ROI    cv::Mat imageROI= image(cv::Rect(110,260,35,40));    cv::rectangle(image, cv::Rect(110,260,35,40),cv::Scalar(0,0,255));

获取直方图:

// Get the Hue histogram    int minSat=65;    ColorHistogram hc;    cv::Mat colorhist= hc.getHueHistogram(imageROI,minSat);

归一化直方图:

cv::normalize(histogram,histogram,1.0);

反向投影直方图的过程包括:从归一化后的直方图中读取概率值,并把输入图像中的每个像素替换成与之对应的概率值,OpenCV中的

calcBackProject可以完成此任务。 cv::calcBackProject(&image,                      1,    // we only use one image at a time                channels,  // vector specifying what //histogram dimensions belong to what image channels                shistogram,   // the histogram we are using                result,       // the resulting back projection image                 ranges,       // the range of values, for each dimension                 255.0         // the scaling factor is chosen such that a histogram value of 1 maps to 255           );

做阈值处理,得到可能是目标的区域:

cv::threshold(result,result,threshold,255,cv::THRESHOLD_BINARY);
原创粉丝点击