OpenCV学习笔记四-用直方图统计像素

OpenCV视觉编程攻略第2版第三章

Chapter4.2计算图像直方图

class Histogram1D {
private:
    int histSize[1];            //直方图中箱子的数量
    float hranges[2];           //值范围
    const float* ranges[1];     //值范围的指针
    int channels[1];            //要检查的通道数量
public:
    Histogram1D(){
        histSize[0] = 256;      //256个箱子    
        hranges[0] = 0.0;       //从0开始(不含)
        hranges[1] = 256.0;     //到256(不含)
        ranges[0] = hranges;    
        channels[0] = 0;
    }

    cv::Mat getHistogram(const cv::Mat &image) {
        cv::Mat hist;
        cv::calcHist(&image,
            1,          //仅作为一个图像的直方图
            channels,   //使用的通道
            cv::Mat(),  //不适用掩码
            hist,       //作为结果的直方图
            1,          //这是一维的直方图
            histSize,   //箱子数量
            ranges      //像素值的范围
        );
        return hist;
    }

    cv::Mat getHistogramImage(const cv::Mat &image, int zoom = 1) {
        //计算直方图
        cv::Mat hist = getHistogram(image);
        //创建图像
        return getImageOfHistogram(hist, zoom);
    }

    static cv::Mat getImageOfHistogram(const cv::Mat &hist, int zoom) {
        //获取箱子值得最大值和最小值
        double maxVal = 0;
        double minVal = 0;
        cv::minMaxLoc(hist, &minVal, &maxVal, 0, 0);
        //获取直方图的大小
        int histSize = hist.rows;
        cv::Mat histImg(histSize*zoom, histSize*zoom, CV_8U, cv::Scalar(255));

        //设置最高点为90%(即图像高度)的箱子个数
        int hpt = static_cast<int>(0.9*histSize);
        //为每个箱子画垂直线
        for (auto h = 0; h < histSize; ++h) {
            auto 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;
    }
};

int main()
{
    cv::Mat image = cv::imread("../pictures/4.png", 0);
    Histogram1D h;
    cv::namedWindow("Image");
    cv::imshow("Image", h.getHistogramImage(image));
    cv::waitKey(0);
    return 0;
}

OpenCV学习笔记四-用直方图统计像素_第1张图片

Chapter4.3利用查找表修改图像外观

    static cv::Mat applyLookUp(const cv::Mat &image, const cv::Mat &lookup)
    {
        cv::Mat result;
        //LUT函数在图像上应用查找表,查找表定义了如何把像素值转换成新的值
        cv::LUT(image, lookup, result);
        return result;
    }

反相
OpenCV学习笔记四-用直方图统计像素_第2张图片

//利用查找表更加高效实现减色
void colorReduce(cv::Mat &image, int div = 64) {
    cv::Mat lookup(1, 256, CV_8U);
    for (auto i = 0; i < 256; ++i)
        lookup.at(i) = i / div*div + div / 2;
    cv::LUT(image, lookup, image);
}

Chapter4.4直方图均衡化

    cv::Mat image = cv::imread("../pictures/4.png", 0);
    cv::Mat result;
    //直方图均衡化处理函数
    cv::equalizeHist(image, result);

均衡化效果,图像的质量有所提升
OpenCV学习笔记四-用直方图统计像素_第3张图片

你可能感兴趣的:(OpenCV学习笔记四-用直方图统计像素)