• Matlab/C++源码实现RGB通道与HSV通道的转换(效果对比Halcon)


    HSV通道的含义

    HSV通道是指图像处理中的一种颜色模型,它由色调(Hue)、饱和度(Saturation)和明度(Value)三个通道组成。色调表示颜色的种类,饱和度表示颜色的纯度或鲜艳程度,明度表示颜色的亮度。HSV通道常用于图像处理中的颜色分析、颜色过滤、颜色调整等任务,它相对于其他颜色模型具有更直观和易于调节的特点,因此被广泛应用于计算机视觉和图像处理的领域。

    Halcon算子例程

    read_image (Image, 'D:/lena.jpg')
    decompose3 (Image, ImageR, ImageG, ImageB)
    trans_from_rgb (ImageR, ImageG, ImageB, ImageH, ImageS, ImageV, 'hsv')
    trans_to_rgb (ImageH, ImageS, ImageV, ImageR1, ImageG1, ImageB1, 'hsv')
    compose3 (ImageR1, ImageG1, ImageB1, MultiChannelImage)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    这里先将三通道RGB三通道拆开成单独的通道,再将RGB与HSV通道互相转换,最后将三通道图像合并成RGB图像。
    Halcon的图像效果是:
    在这里插入图片描述

    源代码实现

    RGB转成HSV

    在这里插入图片描述

    这里需要注意的是,halcon这里将HSV三通道的取值范围作了说明,H通道的数值范围是0到2*pi,S通道的数值范围是0到1,V通道的数值范围是0到1。而常用的图像为BYTE字节型,数值范围是0到255,这里对公式做了修改,使Matlab得出的图像数据范围是0到255,可以直接显示,这里可以从matlab的workspace中看到计算过程。
    以下便是使用Matlab实现trans_from_rgb的效果

    trans_from_rgb (ImageR, ImageG, ImageB, ImageH, ImageS, ImageV, 'hsv')
    
    • 1
    Matlab源码
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %代码--RGB通道转HSV通道
    %时间:2023.9
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    clc;
    image=imread('D:\lena.jpg');
    [height,width,channels]=size(image);
    figure;
    imshow(image);
    title('rgb-image');
    image_R=image(:,:,1);
    image_R=double(image_R);
    image_G=image(:,:,2);
    image_G=double(image_G);
    image_B=image(:,:,3);
    image_B=double(image_B);
    
    %%%转化成HSV通道
    H_image = zeros(height,width);
    S_image = zeros(height,width);
    V_image = zeros(height,width);
    
     %%RGB转成HSV
    for i=1:1:height
         for j=1:1:width
             %%%计算三通道的最大最小值计算
             image_matrix = [image_R(i,j), image_G(i,j), image_B(i,j)];
             maxValue = max(image_matrix);
             minValue = min(image_matrix);
             V_image(i,j) = maxValue;
             if(maxValue == minValue)
                 S_image(i,j) = 0;
                 H_image(i,j) = 0;
             else
                  %%%计算饱和度
                  S_image(i,j) = (maxValue - minValue)*255/minValue;
                  %%%计算H通道
                  if(maxValue == image_R(i,j))
                      H_image(i,j) = 42.5.*(image_G(i,j) - image_B(i,j))./(maxValue - minValue);
                  elseif(maxValue == image_G(i,j))
                      H_image(i,j) = 42.5 * (2 + (image_B(i,j) - image_R(i,j)) / (maxValue - minValue));
                  elseif(maxValue == image_B(i,j)) 
                      H_image(i,j) = 42.5 * (4 + (image_R(i,j) - image_G(i,j)) / (maxValue - minValue));
                  end
             end
         end
    end
    
     %%%RGB要取整
    H_image = uint8(H_image);
    S_image = uint8(S_image);
    V_image = uint8(V_image);
    
    figure;
    imshow(H_image);
    title('H_image');
    
    figure;
    imshow(S_image);
    title('S_image');
    
    figure;
    imshow(V_image);
    title('V_image');
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64

    最终实现的效果是:
    在这里插入图片描述
    最终验证的效果与halcon效果一致;

    同时,以上代码采用C++实现的话如下所示,这里为了保证精度,输出结果采用的是double类型,但是范围也是0到255之间,要显示的话,需要转化为unsigned char类型:

    C++源码
    //将RGB图像转化成HSV图像
    /*
    输入:  rData : r通道图像
    		gData : g通道图像
    		bData : b通道图像
    输出:  hDoubleData : h通道图像, h通道采用double类型,保留精度
    		sDoubleData : s通道图像,s通道采用double类型,保留精度
    		vDoubleData : v通道图像,v通道采用double类型,保留精度
    */
    void trans_from_rgb(unsigned char *rData, unsigned char *gData, unsigned char *bData, double *hDoubleData, double *sDoubleData, double *vDoubleData, int height, int width)
    {
    	if ((height <= 0) || (width <= 0))
    		return;
    	//在函数外部分配好内存空间
    	if (rData == NULL || gData == NULL || bData == NULL || hDoubleData == NULL || sDoubleData == NULL || vDoubleData == NULL)
    		return;
    	int i;
    	unsigned char minValue,maxValue;
    	for (i = 0; i < width * height; i++){
    		//V通道数据,三通道的最大值
    		maxValue = std::max(std::max(rData[i], gData[i]), bData[i]);
    		minValue = std::min(std::min(rData[i], gData[i]), bData[i]);
    		vDoubleData[i] = maxValue;
    		if (maxValue == minValue){
    			sDoubleData[i] = 0;
    			hDoubleData[i] = 0;
    		}
    		else{
    			//S通道
    			sDoubleData[i] = (maxValue - minValue)*255.0 / maxValue;
    			//H通道
    			if (maxValue == rData[i])
    				hDoubleData[i] = 42.5 * (gData[i] - bData[i]) / (maxValue - minValue);    
    			else if (maxValue == gData[i])
    				hDoubleData[i] = 42.5 * (2 + (bData[i] - rData[i]) / (maxValue - minValue));
    			else if (maxValue == bData[i])
    				hDoubleData[i] = 42.5 * (4 + (rData[i] - gData[i]) / (maxValue - minValue));
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    HSV转成RGB

    halcon给出的公式说明为:
    在这里插入图片描述

    Matlab源码

    同样的,采用Matlab实现:

    %%%%%%%%%%%%%%%%%%%%%%%%%%%
    %代码--HSV通道转RGB通道
    %时间:2023.9
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%
    clc;
    image1=imread('D:\lena.jpg');
    [height,width,channels]=size(image1);
    image_H=double(image1);
    image2=imread('E:\S_image.bmp');
    image_S=double(image2);
    image3=imread('E:\V_image.bmp');
    image_V=double(image3);
    
    %%%转化成RGB通道
    R_image = zeros(height,width);
    G_image = zeros(height,width);
    B_image = zeros(height,width);
    
    %%%HSV转成RGB
    for i=1:1:height
         for j=1:1:width
            if(image_S(i,j) == 0)
                R_image(i,j) = image_V(i,j);
                G_image(i,j) = image_V(i,j);
                B_image(i,j) = image_V(i,j);
            else
                %%Hi = floor(image_H(i,j)*2*pi/255/deg2rad(60));    %%归一化到02*pi
                Hi = floor(image_H(i,j)*0.025);
                Hf = image_H(i,j)*0.025 - Hi;
                %%%%根据H的值,将C,X,m分别对应到RGB三个分量上
                if(Hi == 0)
                    R_image(i,j) = image_V(i,j);
                    G_image(i,j) = image_V(i,j) * (1 - image_S(i,j)/255*(1-Hf));
                    B_image(i,j) = image_V(i,j) * (1 - image_S(i,j)/255);
                elseif(Hi == 1)
                    R_image(i,j) = image_V(i,j) * (1 - image_S(i,j)/255*Hf);
                    G_image(i,j) = image_V(i,j);
                    B_image(i,j) = image_V(i,j) * (1 - image_S(i,j)/255);
                elseif(Hi == 2)
                    R_image(i,j) = image_V(i,j) * (1 - image_S(i,j)/255);
                    G_image(i,j) = image_V(i,j);
                    B_image(i,j) = image_V(i,j) * (1 - image_S(i,j)/255*(1-Hf));
                elseif(Hi == 3)
                    R_image(i,j) = image_V(i,j) * (1 - image_S(i,j)/255);
                    G_image(i,j) = image_V(i,j) * (1 - image_S(i,j)/255*Hf);
                    B_image(i,j) = image_V(i,j);
                elseif(Hi == 4)
                    R_image(i,j) = image_V(i,j) * (1 - image_S(i,j)/255*(1-Hf));
                    G_image(i,j) = image_V(i,j) * (1 - image_S(i,j)/255);
                    B_image(i,j) = image_V(i,j);
                elseif(Hi == 5)
                    R_image(i,j) = image_V(i,j);
                    G_image(i,j) = image_V(i,j) * (1 - image_S(i,j)/255);
                    B_image(i,j) = image_V(i,j) * (1 - image_S(i,j)/255*Hf);
                end
            end
         end
    end
    
    %%%RGB要取整
    R_image = uint8(R_image);
    G_image = uint8(G_image);
    B_image = uint8(B_image);
    
    figure;
    imshow(R_image);
    title('R_image');
    
    figure;
    imshow(G_image);
    title('G_image');
    
    figure;
    imshow(B_image);
    title('B_image');
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75

    最终实现的效果是:
    在这里插入图片描述
    可以看出,与Halcon效果一致;

    C++源码

    同样的,采用C++实现:

    //将HSV图像转化成RGB图像
    /*
    输入:  hDoubleData : h通道图像 ,h通道采用double类型,保留精度
    		sDoubleData : s通道图像 ,s通道采用double类型,保留精度
    		vDoubleData : v通道图像 ,v通道采用double类型,保留精度
    输出:  rDoubleData : r通道图像 ,r通道采用double类型,保留精度
    		gDoubleData : g通道图像 ,g通道采用double类型,保留精度
    		bDoubleData : b通道图像 ,b通道采用double类型,保留精度
    */
    void trans_to_rgb(double *hDoubleData, double *sDoubleData, double *vDoubleData, double *rDoubleData, double *gDoubleData, double *bDoubleData, int height, int width)
    {
    	if ((height <= 0) || (width <= 0))
    		return;
    	if (rDoubleData == NULL || gDoubleData == NULL || bDoubleData == NULL || hDoubleData == NULL || sDoubleData == NULL || vDoubleData == NULL)
    		return;
    	int i;
    	double Hi, Hf;
    	for (i = 0; i < width * height; i++){
    		if (sDoubleData[i] > 0){
    			Hi = floor(hDoubleData[i] * 0.025);
    			Hf = hDoubleData[i] * 0.025 - Hi;
    			if (Hi == 0){
    				rDoubleData[i] = vDoubleData[i];
    				gDoubleData[i] = vDoubleData[i] * (1 - sDoubleData[i] / 255.0*(1 - Hf));
    				bDoubleData[i] = vDoubleData[i] * (1 - sDoubleData[i] / 255.0);
    			}
    			else if (Hi == 1){
    				rDoubleData[i] = vDoubleData[i] * (1 - sDoubleData[i] / 255.0 * Hf);
    				gDoubleData[i] = vDoubleData[i];
    				bDoubleData[i] = vDoubleData[i] * (1 - sDoubleData[i] / 255.0);
    			}
    			else if (Hi == 2){
    				rDoubleData[i] = vDoubleData[i] * (1 - sDoubleData[i] / 255.0);
    				gDoubleData[i] = vDoubleData[i];
    				bDoubleData[i] = vDoubleData[i] * (1 - sDoubleData[i] / 255.0*(1 - Hf));
    			}
    			else if (Hi == 3){
    				rDoubleData[i] = vDoubleData[i] * (1 - sDoubleData[i] / 255.0);
    				gDoubleData[i] = vDoubleData[i] * (1 - sDoubleData[i] / 255.0 * Hf);
    				bDoubleData[i] = vDoubleData[i];
    			}
    			else if (Hi == 4){
    				rDoubleData[i] = vDoubleData[i] * (1 - sDoubleData[i] / 255.0*(1 - Hf));
    				gDoubleData[i] = vDoubleData[i] * (1 - sDoubleData[i] / 255.0);
    				bDoubleData[i] = vDoubleData[i];
    			}
    			else if (Hi == 5){
    				rDoubleData[i] = vDoubleData[i];
    				gDoubleData[i] = vDoubleData[i] * (1 - sDoubleData[i] / 255.0);
    				bDoubleData[i] = vDoubleData[i] * (1 - sDoubleData[i] / 255.0 * Hf);
    			}
    		}
    		else{
    			rDoubleData[i] = gDoubleData[i] = bDoubleData[i] = vDoubleData[i];
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    通道拆分与合并C++源代码实现

    三通道拆分

    Halcon中,拆分三通道的算子为:

    decompose3 (Image, ImageR, ImageG, ImageB)
    
    • 1

    对应的拆分三通道图像的C++函数为:

    //拆分三通道图像
    /*
    输入:  srcData : 三通道图像,内存排列方式是BGRBGRBGR......
    输出:  rData : r通道图像
    		gData : g通道图像
    		bData : b通道图像
    */
    void decompose3(unsigned char *srcData, unsigned char *rData, unsigned char *gData, unsigned char *bData, int height, int width)
    {
    	if ((height <= 0) || (width <= 0))
    		return;
    	if (srcData == NULL || rData == NULL || gData == NULL || bData == NULL)
    		return;
    	int i;
    #pragma omp parallel for num_threads(3)
    	for (i = 0; i < width * height; i++)
    	{
    		bData[i] = srcData[3 * i];
    		gData[i] = srcData[3 * i + 1];
    		rData[i] = srcData[3 * i + 2];
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    三通道合并

    Halcon中,拆分三通道的算子为:

    compose3 (ImageR1, ImageG1, ImageB1, MultiChannelImage)
    
    • 1

    对应的合并三通道图像的C++函数为:

    //合并三通道图像
    /*
    输入:  rData : r通道图像
    		gData : g通道图像
    		bData : b通道图像
    输出:  bgrData:彩色图像,合并成BGRBGR.....排列
    */
    void compose3(unsigned char *rData, unsigned char *gData, unsigned char *bData, unsigned char *bgrData, int height, int width)
    {
    	if ((height <= 0) || (width <= 0))
    		return;
    	if (bgrData == NULL || rData == NULL || gData == NULL || bData == NULL)
    		return;
    	int i;
    #pragma omp parallel for num_threads(3)
    	for (i = 0; i < width * height; i++)
    	{
    		bgrData[3 * i] = bData[i];
    		bgrData[3 * i + 1] = gData[i];
    		bgrData[3 * i + 2] = rData[i];
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
  • 相关阅读:
    java毕业设计超市管理系统Mybatis+系统+数据库+调试部署
    SpringBoot:使用jpa实现对Apache Geode的基本操作
    OpenCV图像处理学习九,双边滤波器 (Bilateral Filter)和中位数滤波器 (Median Filter)
    Java刷题面试系列习题(七)
    java设计模式之代理模式
    ELF 文件介绍
    猿创征文 | 云原生领域之容器日常使用工具推荐
    指望识别技术
    缓存同步之 RabbitMQ 和 Canal
    每章一篇博客带你拿下吉林大学JAVAEE期末(四:JDBC)
  • 原文地址:https://blog.csdn.net/qq_43376782/article/details/133861387