怎样用C语言实现图片的RGB颜色空间向Lab颜色空间的转化??

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了怎样用C语言实现图片的RGB颜色空间向Lab颜色空间的转化??相关的知识,希望对你有一定的参考价值。

具体的转化我会 主要是想知道如何获取图片的RGB这三个值???
帮我用C实现如上matlab的程序也行!谢谢啦
i=imread(filename);
imshow(i);
[l,a,b]=RGB2Lab(i);
%ia=hist(a);
%bar(ia);
da=mean2(a); %LAB颜色空间中a分量的均值
disp(da);
db=mean2(b); %LAB颜色空间中b分量的均值
disp(db);
D=sqrt(da^2+db^2);
disp(D);
ma=SumMatAv(a,da);
disp(ma);
mb=SumMatAv(b,db);
disp(mb);
M=sqrt(ma^2+mb^2);
disp(M);
K=D/M;

应该是html中的javascript代码,也可能是其他的用处很多,有时JAVASCRIPT中滤镜还要用!

颜色代码有以下几种表示方法:

HSB色系:利用的是人的视觉而产生的不同影响,用色值H,饱和度S,亮度B表示.

Lab色系,这是一种将自然界中所有颜色的转化,有些人眼是无法分辨的,这是各色系中色域最广的一个!用的时候不多.

RGB色系:这个是利用广告学中的三原色原理,纯色系,它认为各种颜色都是由R红G绿和B蓝来以不同比例混合(相加)而成.正如上文中的一个,使用24真彩色时每个最大值是255,最小是0,最后的一个数字,可能是滤镜要用到的滤色什么的,不见全部的东西是不知道的!同时还有另一种表示方法:6位16进制值:如FFFFFF一般前还要加个#号,前两位是红中间两位是绿最后两位是蓝.可以与数字相互转化.最常用的.

CMYK色系:由于广告中的印刷而产生的一种色系,也是混合,但是是减法色系.三原色是品红M,黄Y,青C,因为三色最终混合不能得到黑色,所以加入一个K黑色.这个用于印刷设计.色域没有RGB大.同时还是两个RGB三原色的混合(理论上),其中三原色都不复色,所以是减色系.表示方式是以%值表示,最大是100%.

WEB色系:是RGB的一个子色系(色域),当然色域最小.用以网页等设计,只能表示256种颜色,表示方法与RGB同.但是是按比例缩小色域,如RGB(0,0,0)就是WEB色能表示的,RGB(3,0,0)也是能表示的;但RGB(2,0,0)在WEB中就是RGB(3,0,0);换句话来说,不是RGB色系的一部分.

这没有专门的网站的,要多看一下书,一般平设开始会介绍一部分的相关知识的.
参考技术A HSB色系:利用的是人的视觉而产生的不同影响,用色值H,饱和度S,亮度B表示. Lab色系,这是一种将自然界中所有颜色的转化,有些人眼是无法分辨的,这是 参考技术B (各分量数值范围:R/G/B: 0~255; L: 0~100, a/b:0~255)
RGB---Lab:
X = 0.412453*R + 0.357580*G + 0.180423*B;
Y = 0.212671*R + 0.715160*G + 0.072169*B;
Z = 0.019334*R + 0.119193*G + 0.950227*B;
X = X/(255*0.950456);
Y = Y/255;
Z = Z/(255*1.088754);

如果Y > 0.008856,则 :
fY = Y^(1/3);
fX = X^(1/3);
fZ = Z^(1/3);
L= 116*fY - 16;
如果Y < 0.008856,则 fY = 7.787*Y + 16/116;
fX = 7.787*X + 16/116;
fZ = 7.787*Z + 16/116;
L= 903.3*Y;
a = 500.0*(fX - fY) +128;
b = 200.0*(fY - fZ) +128;
根据上面公式,很容易写出下面转换的函数:
double BLACK = 20;
double YELLOW = 70;
void RGB2Lab(double R, double G, double B, double &L, double &a, double &b)

double X, Y, Z, fX, fY, fZ;

X = 0.412453*R + 0.357580*G + 0.180423*B;
Y = 0.212671*R + 0.715160*G + 0.072169*B;
Z = 0.019334*R + 0.119193*G + 0.950227*B;

X /= (255 * 0.950456);
Y /= 255;
Z /= (255 * 1.088754);

if (Y > 0.008856)

fY = pow(Y, 1.0/3.0);
L = 116.0*fY - 16.0;

else

fY = 7.787*Y + 16.0/116.0;
L = 903.3*Y;


if (X > 0.008856)
fX = pow(X, 1.0/3.0);
else
fX = 7.787*X + 16.0/116.0;

if (Z > 0.008856)
fZ = pow(Z, 1.0/3.0);
else
fZ = 7.787*Z + 16.0/116.0;

a = 500.0*(fX - fY);
b = 200.0*(fY - fZ);

if (L < BLACK)

a *= exp((L - BLACK) / (BLACK / 4));
b *= exp((L - BLACK) / (BLACK / 4));
L = BLACK;

if (b > YELLOW)
b = YELLOW;

追问

具体的转化我会 主要是想知道如何获取图片的RGB这三个值???

追答

PIC_RGB=imread('c:\1.bmp');
PIC_RGB(1,1,1)就表示第一个像素的R值,同理PIC_RGB(1,1,2)就表示第一个像素的G值,PIC_RGB(1,1,3)就表示第一个像素的B值。这是您想要的答案吗?

简单实现图片颜色风格转换

今天我们尝试用两种简单的,快速的方法实现图片的风格转换,这不仅是一个有趣的实践,里面使用的一些方法在以后的图像处理中也能经常看见。

Lab颜色空间转换

第一种方法的原理出自Reinhard的文章《Color Transfer between Images》,我们可以分别利用 Lab* 颜色空间以及每个 L*、a* 和 b* 通道的均值和标准差,在两个图像之间传输颜色。

“Lab颜色空间是什么,我只听说过RGB颜色空间啊!”相信很多人都有这样的疑问,其实还有许多类似的彩色模型。这些具体是怎么样的,我暂时无法解释清楚。我在这里就简单介绍下Lab,L代表亮度,a和b代表颜色,Lab就是由这三个变量共同决定的。我们可以看到,它把亮度单独拿出来当作一个参考,人对颜色的感知会随着环境的亮度而改变,以此我们大概能理解“Lab颜色空间是基于人对颜色的感觉来设计的,更具体地说,它是感知均匀的”这一个官方说明。

详细的计算过程在下面代码的color_transfer()函数里都清楚地写了出来,可以自己尝试把它的公式列出来。

以前,我总听说火烧云这一个说法。于是,这次的例子我们就以火为源图像,云朵为目标图像,看看转换的结果吧。

import numpy as np
import cv2
import argparse

def color_transfer(source, target):
	source = cv2.cvtColor(source, cv2.COLOR_BGR2LAB).astype("float32")
	target = cv2.cvtColor(target, cv2.COLOR_BGR2LAB).astype("float32")
	# compute color statistics for the source and target images
	(lMeanSrc, lStdSrc, aMeanSrc, aStdSrc, bMeanSrc, bStdSrc) = image_stats(source)
	(lMeanTar, lStdTar, aMeanTar, aStdTar, bMeanTar, bStdTar) = image_stats(target)
	(l, a, b) = cv2.split(target)
	l -= lMeanTar
	a -= aMeanTar
	b -= bMeanTar
	l = (lStdTar / lStdSrc) * l
	a = (aStdTar / aStdSrc) * a
	b = (bStdTar / bStdSrc) * b
	l += lMeanSrc
	a += aMeanSrc
	b += bMeanSrc
	l = np.clip(l, 0, 255)
	a = np.clip(a, 0, 255)
	b = np.clip(b, 0, 255)
	transfer = cv2.merge([l, a, b])
	transfer = cv2.cvtColor(transfer.astype("uint8"), cv2.COLOR_LAB2BGR)
	return transfer

def image_stats(image):
	(l, a, b) = cv2.split(image)
	(lMean, lStd) = (l.mean(), l.std())
	(aMean, aStd) = (a.mean(), a.std())
	(bMean, bStd) = (b.mean(), b.std())
	return (lMean, lStd, aMean, aStd, bMean, bStd)

ap=argparse.ArgumentParser()
ap.add_argument("-s","--source",required=True)
ap.add_argument("-t","--target",required=True)
args=vars(ap.parse_args())

source=cv2.imread(args["source"])
target=cv2.imread(args["target"])
cv2.imshow("Source",source)
cv2.imshow("Target",target)
transfer=color_transfer(source,target)

这个算法非常快,但有一个特别的缺点——它依赖于全局颜色统计,因此具有相似像素强度值的大区域会显着影响平均值,而且它的改变也是全局的变化,非常生硬。

直方图匹配

我们看到了上面有这么一个缺点,那么我们如何处理才能使颜色转换不是那么生硬地全局统一变换呢?当然方法有很多,但是这篇文章我们只专注“简单”二字,所以我接下来将介绍直方图匹配。

直方图匹配,或者说直方图规定化,大家可以稍微记住这个名词,因为可以和下一篇的直方图均衡化进行一个类比。关于它的原理我打算拿出教材中的一个计算列表,带着大家算一遍,应该就能完全明白它的过程,毕竟当初我就是这么理解的。

计算示例:其实也有对应的数学公式来描述这一过程,但我相信大部分人看到这些就头疼。我们就直接引入一个简单的例子吧,我们假设一个8位的像素图,表格中的小数表示该像素级所占整体的比例。

在正式开始之前,我还得介绍几个概念。累计直方图指的是小于等于该像素级所有像素的数量,比如2像素级就会统计0,1,2所有的数量。映射的规则也可以按照下面的解释简单理解,但并不完全正确,SML映射关注附近距离最近的点,GML映射关注小于某一值的点。


我们以原始像素级1为切入点看一下,其比例为0.25,对应累计为0.44 。规定直方图(即我们参考的图)只有三个像素级,直方图和累积也都列写了出来。根据SML映射,累计值为0.44的像素级1(原始)在规定累计直方图里更接近像素级3(参考)对应的0.2,所以像素级为1在新的图里变成了像素级3。根据GML映射,累计值为0.44的像素级1(原始)在规定累计直方图里远大于像素级3(参考)对应的0.2,但小于像素级5(参考)对应的0.8,所以像素级为1在新的图里变成了像素级5 。

根据结果我们可以看到GML的映射结果是更符合变换后的图像的。

好,那让我们试一下,就以广州的小蛮腰为例子。


万幸的是,我们不需要使用代码来一步步实现上述的计算,而是调用一下match_histograms()函数即可。在这个函数之前有一个判断multi,用来判别我们输入的是彩色图还是灰度图。

from skimage import exposure
import matplotlib.pyplot as plt
import argparse
import cv2

ap=argparse.ArgumentParser()
ap.add_argument("-s","--source",required=True)
ap.add_argument("-t","--target",required=True)
args=vars(ap.parse_args())

source=cv2.imread(args["source"])
target=cv2.imread(args["target"])
multi=True if source.shape[-1]>1 else False
matched=exposure.match_histograms(target,source,multichannel=
        multi)

cv2.imshow("source",source)
cv2.imshow("target",target)
cv2.imshow("matched",matched)
cv2.waitKey(0)

变换1:

变换2:

我个人觉得效果是好了不少,不知道大家怎么想的。当然,这篇文章里我们只是介绍了简单的,快速的风格转换应用。相对的,也有一些现在非常流行的GAN之类的方法,我们一步步来。

“本站所有文章均为原创,欢迎转载,请注明文章出处:https://blog.csdn.net/kasami_/article/details/123948422。百度和各类采集站皆不可信,搜索请谨慎鉴别。技术类文章一般都有时效性,本人习惯不定期对自己的博文进行修正和更新,因此请访问出处以查看本文的最新版本。”

以上是关于怎样用C语言实现图片的RGB颜色空间向Lab颜色空间的转化??的主要内容,如果未能解决你的问题,请参考以下文章

RGB与Lab颜色空间互相转换

Lab颜色空间进行颜色提取 及其实现

RGB、CMY、CMYK、YUV、HSV、HSI、LAB颜色空间详解

Lab颜色空间

基于 OpenCV 与 Java 两个语言版本实现获取某一图片特定区域的颜色对比度

pytorchtensor张量vector向量numpy array数组image图像RGB空间LAB空间之间相互转换大全