想把图像转成 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 不同? |
![]() | span class="no">3 lcdtyph 2019-10-16 13:53:33 +08:00 ![]() @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 47jm9ozp 2019-10-16 15:42:58 +08:00 一共就这么几行,还贴伪代码,是让大家脑补还原再帮你 debug 吗? 然后出来结果怎么样得也没说,只描述了不一样,到底怎么不一样 前面猜的差不多了,要么是 8UC1 溢出,还可能 python 和 C++的 RGB 顺序不一样 |
![]() | 12 47jm9ozp 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 47jm9ozp 2019-10-16 15:55:09 +08:00 |
![]() | 16 47jm9ozp 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 47jm9ozp 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 47jm9ozp 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 我就懵了额。 |