想把图像转成 CIE 色度下的图片,执行了如下操作
#B,G,R = split(img)
/*
vector<Mat>BGR;
split(img,BGR);
B,G,R = BGR[0],BGR[1],BGR[2]
*/
r = R / (R + G + B)
g = G / (R + G + B)
b = 1 - r - g
发现两者的结果不同,有大佬来解惑么~
手写补充下
//... ...
using namespace std;
using namespace cv;
//... ...
vector<Mat> BGR;
Mat img = imread(your_path) ;
split(img,BGR);
Mat B,G,R,r,g,b;
BGR[0].copyTo(B);
BGR[1].copyTo(G);
BGR[2].copyTo(R);
r = R / (R + G + B);
g = G / (R + G + B);
b = (1 - r - g);
//可选
//r *= 255;
//g *= 255;
//b *= 255;
b.copyTo(BGR[0]);
g.copyTo(BGR[1]);
r.copyTo(BGR[2]);
merage(BGR,img);
imwrite(your_path,img);
#... ...
img = cv2.imread(your_path)
B,G,R = cv2.split(img)
r = R / (R + G + B);
g = G / (R + G + B);
b = (1 - r - g);
#可选
#r *= 255;
#g *= 255;
#b *= 255;
img = cv2.merage([b,g,r])
cv2.imwrite(your_path,img)
1
Mohanson 2019-10-16 11:48:16 +08:00
检查下变量 R, G, B 是不是 float.
|
2
SeaRecluse OP @Mohanson 有检查,然后为了避免运算符重载的问题,我还遍历了手动操作,但是结果还是不一样,难道是 py 和 C++的 imwrite 不同?
|
3
lcdtyph 2019-10-16 13:53:33 +08:00 1
@SeaRecluse #2
注释里的东西是实际代码吗? 如果是的话 ``` B,G,R = BGR[0],BGR[1],BGR[2] ``` 相当于 B, G, (R = BGR[0]), BGR[1], BGR[2] 这在 C++里是逗号表达式,并不是 unpacking |
4
stebest 2019-10-16 14:06:31 +08:00
这个语法是 C 还是 py ?
|
5
SeaRecluse OP |
6
capbone 2019-10-16 14:46:24 +08:00
图像颜色这种东西可视化一下不就清楚问题在哪了?而且 r = R / (R + G + B) 这种哪是 CIE 啊
|
7
Justkkk 2019-10-16 14:49:41 +08:00
opencv r,g,b 是 uchar 存储的,8 位( 0-255 ),你 r+b+g 可能会超过 255 的
|
8
hitmanx 2019-10-16 14:56:21 +08:00
一共就那么点操作,那么几行代码,还贴伪代码...变量类型让大家猜吗?
|
9
SeaRecluse OP @Justkkk 我修改了 Mat 开始的空间类型为 32FC1,结果是一样的。py 这里不会归到 0-255 内,然后存储再读取之后的值,看不出来是怎么转换的。
|
10
lcdtyph 2019-10-16 15:37:01 +08:00 via iPhone
@SeaRecluse 按你的描述不是应该修改成 8UC1 吗…
|
11
ooxxcc 2019-10-16 15:42:58 +08:00
一共就这么几行,还贴伪代码,是让大家脑补还原再帮你 debug 吗?
然后出来结果怎么样得也没说,只描述了不一样,到底怎么不一样 前面猜的差不多了,要么是 8UC1 溢出,还可能 python 和 C++的 RGB 顺序不一样 |
12
ooxxcc 2019-10-16 15:46:02 +08:00
还有,opencv 自带颜色空间转换,你何苦自己写……
https://docs.opencv.org/3.4/de/d25/imgproc_color_conversions.html 另外 CIE 有 CIE XYZ/ CIE L*a*b*/CIE L*u*v*,不过我看你这个怎么好像哪个都不是…… |
13
SeaRecluse OP @lcdtyph 默认分割后就是 8UC1,py 下如果手动执行操作的话,我新建的数据是 float32 位的,所以为了对应也为了防止溢出就改为 32FC1 的。
|
14
SeaRecluse OP @ooxxcc 这里是我没说清楚,一开始我是好奇类似 R / (R + G + B)的归一化方式是啥玩意,随便搜了下,搜到了 CIE 1931 的色域分布公式,所以就简称 CIE 了。
因为我 py 模拟这个操作的时候,初始化为 float32 时的结果和直接操作的结果相同,而 8UC1 情况下不同,而 C++不论如何的结果都与 py 直接操作不同,所以才有疑问。 |
15
ooxxcc 2019-10-16 15:55:09 +08:00
|
16
ooxxcc 2019-10-16 15:56:16 +08:00
其实主要就是
1.R + G + B 大于 255 处理了没 2.R + G + B 等于 0 处理了没 |
17
SeaRecluse OP @ooxxcc 这个我手动重写时都有考虑。其实这就是全部代码了额- -。C++和 py 只是初始化不太一样而已,随手找张图这样处理一下然后 Imwrite,就能发现 C++ 的结果会全部黑 [因为都小于 1 了,uchar 里会变 0] ,但是 py 的会不一样。
|
18
ooxxcc 2019-10-16 16:27:51 +08:00
@SeaRecluse 没看到你转换成 double 啊……建议学习一下 Mat::copyTo 和 Mat::convertTo 的区别
假如都是 8UC1 的话,你这么除之后当然都是 1 或者 0,imwrite 之后是全黑也是正常的 你现在做的是一个 range 是[0,1]的 8UC1 Mat 保存成图片,全黑是正常表现 python-opencv 我没怎么用过,看起来大概是隐含类型转换,除的时候给你处理成浮点了,保存时候表现不一样 |
19
ooxxcc 2019-10-16 16:30:38 +08:00
比如这一句 r = R / (R + G + B);
里面所有变量都是 unsigned char…… 你觉得会怎么样呢,r 中元素只可能有三个值,0/1/inf (除数为 0,可能抛异常) |
20
SeaRecluse OP @ooxxcc emmm 这个要双持下才会知道差别也太大了- -,我尝试手动转的代码没有贴。现在可以复现 C++下的效果,但是复现不了 Py 下的效果😂
|
21
SeaRecluse OP @ooxxcc 我明白这是合理的,所以反观 py 我就懵了额。
|