彩图在HSV空间直方图均衡化后,对比度为什么只有0.001级别

代码


hsi_f=rgb2hsv(f); %转换成HSI彩色空间
H=hsi_f(:,:,1); %色度分量
S=hsi_f(:,:,2); %饱和度分量
I=hsi_f(:,:,3); %亮度分量
I_equ=histeq(I); %均衡化
hsi_f_equ=cat(3,H,S,I_equ); %整合
fI_equ=hsv2rgb(hsi_f_equ); %转换回RGB空间

subplot(131),imshow(f),title('原图')
subplot(132),imshow(fI_equ),title('RGB均衡化')

C=duibidu4(fI_equ);
fprintf('\nC=%f',C);
fprintf('\n');

%%%%%%%%%%%%%%%%%%%%%%计算对比度函数%%%%%%%%%%%%%%%%

%方法一:中心像素灰度值与周围4近邻像素灰度值之差的平方之和,除以以上平方项的个数。
function[cg] = duibidu4(f)  %f为输入图像,cg为输出的对比度数值,是英文contrast gradient的首字母组合
[m,n] = size(f);            %求原始图像的行数m和列数n
g = padarray(f,[1 1],'symmetric','both');%对原始图像进行扩展,比如50*50的图像,扩展后变成52*52的图像,
                        %扩展只是对原始图像的周边像素进行复制的方法进行
[r,c] = size(g);        %求扩展后图像的行数r和列数c
g = double(g);          %把扩展后图像转变成双精度浮点数
k = 0;                   %定义一数值k,初始值为0
for i=2:r-1
    for j=2:c-1
        k = k+(g(i,j-1)-g(i,j))^2+(g(i-1,j)-g(i,j))^2+(g(i,j+1)-g(i,j))^2+(g(i+1,j)-g(i,j))^2;
    end
end
cg = k/(4*(m-2)*(n-2)+3*(2*(m-2)+2*(n-2))+4*2);%求原始图像对比度

end

计算后对比度只有0.0007,但是在RGB空间对比度就是60

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 你可以看下这个问题的回答https://ask.csdn.net/questions/7656712
  • 这篇博客也不错, 你可以看下HSV与HSI颜色空间的区别以及和RGB之间的转换
  • 除此之外, 这篇博客: Matlab-人机交互中的 二、实现RGB转HSV空间 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:

    代码:

    rgb=imread('peppers.png');%读入图像
    subplot(221),imshow(rgb);title('原始图像')
    hsv=rgb2hsv(rgb); %颜色空间转换
    H=hsv(:,:,1); % 色调
    S=hsv(:,:,2); % 饱和度
    V=hsv(:,:,3); % 亮度
    subplot(221);imshow(rgb); 
    subplot(222);imshow(H);title('色调')
    subplot(223);imshow(S);title('饱和度')
    subplot(224);imshow(V);title('亮度')

  • 以下回答来自chatgpt:

    根据提供的参考资料和代码,问题可能出在对比度计算的方式上。HSV空间和RGB空间的对比度计算方式不同,而在代码中只给出了RGB空间下的对比度计算方式。因此,需要重新计算HSV空间下的对比度,并修改代码来实现。

    下面给出在HSV空间下计算对比度的步骤:

    1. 将彩图转为HSV空间,使用cv::cvtColor函数实现:
    Mat hsv_image;
    cv::cvtColor(image, hsv_image, COLOR_BGR2HSV);
    
    1. 对H,S,V三通道分别执行直方图均衡化
    vector<Mat> hsv_planes;
    split(hsv_image, hsv_planes);
    for(int i=0;i<3;i++)
    {
        equalizeHist(hsv_planes[i], hsv_planes[i]);
    }
    merge(hsv_planes, hsv_image);
    
    1. 将HSV空间图像转回BGR空间
    cv::cvtColor(hsv_image, image, COLOR_HSV2BGR);
    
    1. 计算对比度

    此处对比度计算采用阈值来实现,将像素值小于阈值的像素都设置为0,像素值大于阈值的像素都设置为255,然后计算像素值为255的像素所占比例即可。

    int threshold_value = 128;  // 阈值
    int count = 0;  // 统计像素值为255的像素个数
    for(int i=0;i<image.rows;i++)
    {
        for(int j=0;j<image.cols;j++)
        {
            if(image.at<Vec3b>(i,j)[2] > threshold_value)  // 只考虑图像的亮度通道
            {
                count++;
            }
            if(image.at<Vec3b>(i,j)[2] < threshold_value)
            {
                image.at<Vec3b>(i,j) = Vec3b(0,0,0);  // 小于阈值的像素都设置为0
            }
            else
            {
                image.at<Vec3b>(i,j) = Vec3b(255,255,255);  // 大于阈值的像素都设置为255
            }
        }
    }
    float contrast = (float)count / (image.rows * image.cols);  // 计算对比度
    

    修改后的代码如下所示:

    #include "stdio.h"
    #include<iostream>
    #include<opencv2/opencv.hpp>
    #include<iomanip>
    #include<cmath>
    #include<string>
    
    using namespace std;
    using namespace cv;
    
    
    int main()
    {
        const int num = 157;  //在D:\\test_picture\\%d.png中你要处理的图片数量
        char fileName[50];
        char windowName[50];
        Mat image;
    
        float rateyellow;  //要计算的百分率
        float ratered;
        float rategrey;
        float ratewhite;
        float rateblack;
        float hsv_contrast;
        cout << "序号" << "\t" << "HSV对比度" << "\t" << "黄色区域占比" << "\t" << "红色区域占比" << "\t" << "灰色区域占比""\t" << "白色区域占比""\t" << "黑色占比" << endl;
        for (int k = 1; k <= num; k++){
            //sprintf读入指定路径下的图片序列
            sprintf_s(fileName, "D:\\test_picture\\%d.png", k);
            sprintf_s(windowName, "No%d", k);
            //按照图像文件名读取
            image = imread(fileName);
            // 转换为HSV空间
            Mat hsv_image;
            cv::cvtColor(image, hsv_image, COLOR_BGR2HSV);
            // 对H,S,V三通道分别执行直方图均衡化
            vector<Mat> hsv_planes;
            split(hsv_image, hsv_planes);
            for(int i=0;i<3;i++)
            {
                equalizeHist(hsv_planes[i], hsv_planes[i]);
            }
            merge(hsv_planes, hsv_image);
            // 将HSV空间图像转回BGR空间
            cv::cvtColor(hsv_image, image, COLOR_HSV2BGR);
            // 计算对比度
            int threshold_value = 128;  // 阈值
            int count = 0;  // 统计像素值为255的像素个数
            for(int i=0;i<image.rows;i++)
            {
                for(int j=0;j<image.cols;j++)
                {
                    if(image.at<Vec3b>(i,j)[2] > threshold_value)  // 只考虑图像的亮度通道
                    {
                        count++;
                    }
                    if(image.at<Vec3b>(i,j)[2] < threshold_value)
                    {
                        image.at<Vec3b>(i,j) = Vec3b(0,0,0);  // 小于阈值的像素都设置为0
                    }
                    else
                    {
                        image.at<Vec3b>(i,j) = Vec3b(255,255,255);  // 大于阈值的像素都设置为255
                    }
                }
            }
            hsv_contrast = (float)count / (image.rows * image.cols);  // 计算HSV空间下的对比度
            // 计算各颜色占比
            int numOfyellow = 0;
            int numOfred = 0;
            int numOfgrey = 0;
            int numOfwhite = 0;
            int numOfblack = 0;
            for (int i = 0; i < image.rows; i++)
            {
                for (int j = 0; j <image.cols; j++)   //遍历图片的每一个像素点
                {
                    if ((image.at<Vec3b>(i, j)[0] <= 120 && image.at<Vec3b>(i, j)[1] >= 170 && image.at<Vec3b>(i, j)[2] >= 230)
                            || (image.at<Vec3b>(i, j)[0]>120 && image.at<Vec3b>(i, j)[0] <= 180 && image.at<Vec3b>(i, j)[1] >= 180 &&
                               image.at<Vec3b>(i, j)[2] >= 220)){//对该像素是否为黄色进行判断
                        numOfyellow++;
                    }
                    if (image.at<Vec3b>(i, j)[0] <= 60 && image.at<Vec3b>(i, j)[1] <= 60 && image.at<Vec3b>(i, j)[2] >= 200){//对该像素是否为红色色进行判断
                        numOfred++;
                    }
                    if (image.at<Vec3b>(i, j)[0] <= 220 && image.at<Vec3b>(i, j)[0] >= 60 && abs(image.at<Vec3b>(i, j)[0] - image.at<Vec3b>(i, j)[1]) <= 15 && 
                            abs(image.at<Vec3b>(i, j)[0] - image.at<Vec3b>(i, j)[2]) <= 15){//对该像素是否为灰色进行判断
                        numOfgrey++;
                    }
                    if (image.at<Vec3b>(i, j)[0] >= 235 && image.at<Vec3b>(i, j)[1] >= 235 && image.at<Vec3b>(i, j)[2] >= 235){//对该像素是否为白色进行判断
                        numOfwhite++;
                    }
                    if (image.at<Vec3b>(i, j)[0] <= 45 && image.at<Vec3b>(i, j)[1] <= 45 && image.at<Vec3b>(i, j)[2] <= 45){//对该像素是否为黑色进行判断
                        numOfblack++;
                    }
                }
            }
            rateyellow = (float)numOfyellow / (float)(image.rows * image.cols);
            ratered = (float)numOfred / (float)(image.rows * image.cols);
            rategrey = (float)numOfgrey / (float)(image.rows * image.cols);
            ratewhite = (float)numOfwhite / (float)(image.rows * image.cols);
            rateblack = (float)numOfblack / (float)(image.rows * image.cols);
            cout << "NO" << k << "\t";
            cout << fixed << setprecision(4) << hsv_contrast << "\t";
            cout << fixed << setprecision(4) << rateyellow << "\t" << "\t";
            cout << fixed << setprecision(4) << ratered << "\t" << "\t";
            cout << fixed << setprecision(4) << rategrey << "\t" << "\t";
            cout << fixed << setprecision(4) << ratewhite << "\t" << "\t";
            cout << fixed << setprecision(4) << rateblack << endl;
        }
        return 0;
    }
    

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^