计算图像直方图方法,纠正calcHist调用错误(OpenCV)

第一种 : 循环遍历(时间效率低,不建议采用)

依次遍历图像的像素点,存储不同灰度级的像素点个数
代码(包含画直方图):

bool calcHistograph(Mat img){
    if (!img.data)
        return false;
    Mat gray;
    if (img.channels() == 1)
        img.copyTo(gray);
    else
        cvtColor(img, gray, CV_BGR2GRAY);
    Mat histogram(500, 520, CV_8UC1, Scalar(0, 0, 0));
    float hist[256] = { 0 };
    for (int i = 0; i < gray.rows; i++)
    {
        for (int j = 0; j < gray.cols; j++)
        {
            hist[gray.at<uchar>(i, j)] ++;
        }
    }
    float max = 0;
    for (int i = 0; i < 256; i++)
    {
        if (hist[i] > max)
            max = hist[i];
    }
    for (int i = 0; i < 256; i++)
    {
        line(histogram, Point(i * 2, 500), Point(i * 2,500. - hist[i] / max * 500.), Scalar(255));
        line(histogram, Point(i * 2 + 1, 500), Point(i * 2 + 1, 500. - hist[i] / max * 500.), Scalar(255));
    }
    imshow("histogram", histogram);
    waitKey(10);
    return true;
}

第二种 : 库函数调用(时间效率高,调用时要细心)

定义必要的函数参数,调用calcHist()函数
代码(包含画直方图):

//计算直方图数据 取数据:hist.at<float>(i)
bool calcImgHistData(const Mat &img, MatND &hist, MatND &hist_prob){
    if (!img.data)
        return false;
    const int channels[1] = { 0 };
    const int histSize[1] = { 256 };
    float hrange[2] = { 0, 256 };
    const float *range[1] = { hrange };
    calcHist(&img, 1, channels, Mat(), hist, 1, histSize, range);
    Mat histogram(500, 520, CV_8UC1, Scalar(0, 0, 0));
    float max = 0;
    for (int i = 0; i < 256; i++)
    {
        if (hist.at<float>(i) > max)
            max = hist.at<float>(i);
    }
    for (int i = 0; i < 256; i++)
    {
        line(histogram, Point(i * 2, 500), Point(i * 2,500. - hist.at<float>(i) / max * 500.), Scalar(255));
        line(histogram, Point(i * 2 + 1, 500), Point(i * 2 + 1, 500. - hist.at<float>(i) / max * 500.), Scalar(255));
    }
    imshow("histogram", histogram);
    waitKey(10);
    return true;
}

注意
float hrange[2] = { 0, 256 };
不少童鞋都将256错写成255,结果丢失了灰度级为255的数据

你可能感兴趣的:(opencv,生成图像直方图)