图像处理, py 和 C++下的结果不同 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
SeaRecluse
V2EX    Python

图像处理, py 和 C++下的结果不同

  •  
  •   SeaRecluse 2019-10-16 10:47:16 +08:00 4648 次点击
    这是一个创建于 2195 天前的主题,其中的信息可能已经有所发展或是发生改变。

    想把图像转成 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 

    发现两者的结果不同,有大佬来解惑么~

    第 1 条附言    2019-10-16 16:09:23 +08:00

    手写补充下

    //... ... 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) 
    21 条回复    2019-10-16 16:32:58 +08:00
    Mohanson
        1
    Mohanson  
       2019-10-16 11:48:16 +08:00
    检查下变量 R, G, B 是不是 float.
    SeaRecluse
        2
    SeaRecluse  
    OP
       2019-10-16 13:41:04 +08:00
    @Mohanson 有检查,然后为了避免运算符重载的问题,我还遍历了手动操作,但是结果还是不一样,难道是 py 和 C++的 imwrite 不同?
    lcdtyph
        span class="no">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
    stebest
        4
    stebest  
       2019-10-16 14:06:31 +08:00
    这个语法是 C 还是 py ?
    SeaRecluse
        5
    SeaRecluse  
    OP
       2019-10-16 14:21:06 +08:00
    @lcdtyph @stebest 伪代码
    现在我自己测试的结果是 C++因为变量类型固定的缘故,会比 py 多一步%256。所以会有差别- -
    capbone
        6
    capbone  
       2019-10-16 14:46:24 +08:00
    图像颜色这种东西可视化一下不就清楚问题在哪了?而且 r = R / (R + G + B) 这种哪是 CIE 啊
    Justkkk
        7
    Justkkk  
       2019-10-16 14:49:41 +08:00
    opencv r,g,b 是 uchar 存储的,8 位( 0-255 ),你 r+b+g 可能会超过 255 的
    hitmanx
        8
    hitmanx  
       2019-10-16 14:56:21 +08:00
    一共就那么点操作,那么几行代码,还贴伪代码...变量类型让大家猜吗?
    SeaRecluse
        9
    SeaRecluse  
    OP
       2019-10-16 15:16:42 +08:00
    @Justkkk 我修改了 Mat 开始的空间类型为 32FC1,结果是一样的。py 这里不会归到 0-255 内,然后存储再读取之后的值,看不出来是怎么转换的。
    lcdtyph
        10
    lcdtyph  
       2019-10-16 15:37:01 +08:00 via iPhone
    @SeaRecluse 按你的描述不是应该修改成 8UC1 吗…
    47jm9ozp
        11
    47jm9ozp  
       2019-10-16 15:42:58 +08:00
    一共就这么几行,还贴伪代码,是让大家脑补还原再帮你 debug 吗?

    然后出来结果怎么样得也没说,只描述了不一样,到底怎么不一样

    前面猜的差不多了,要么是 8UC1 溢出,还可能 python 和 C++的 RGB 顺序不一样
    47jm9ozp
        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*,不过我看你这个怎么好像哪个都不是……
    SeaRecluse
        13
    SeaRecluse  
    OP
       2019-10-16 15:46:49 +08:00
    @lcdtyph 默认分割后就是 8UC1,py 下如果手动执行操作的话,我新建的数据是 float32 位的,所以为了对应也为了防止溢出就改为 32FC1 的。
    SeaRecluse
        14
    SeaRecluse  
    OP
       2019-10-16 15:52:47 +08:00
    @ooxxcc 这里是我没说清楚,一开始我是好奇类似 R / (R + G + B)的归一化方式是啥玩意,随便搜了下,搜到了 CIE 1931 的色域分布公式,所以就简称 CIE 了。
    因为我 py 模拟这个操作的时候,初始化为 float32 时的结果和直接操作的结果相同,而 8UC1 情况下不同,而 C++不论如何的结果都与 py 直接操作不同,所以才有疑问。
    47jm9ozp
        15
    47jm9ozp  
       2019-10-16 15:55:09 +08:00
    @SeaRecluse 所以,你说这么多不如贴一下代码,这里一堆大佬会帮你 debug

    不只是初始化的问题,你这个操作过程中随时都可能存在溢出(比如临时变量)
    47jm9ozp
        16
    47jm9ozp  
       2019-10-16 15:56:16 +08:00
    其实主要就是
    1.R + G + B 大于 255 处理了没
    2.R + G + B 等于 0 处理了没
    SeaRecluse
        17
    SeaRecluse  
    OP
       2019-10-16 16:02:37 +08:00
    @ooxxcc 这个我手动重写时都有考虑。其实这就是全部代码了额- -。C++和 py 只是初始化不太一样而已,随手找张图这样处理一下然后 Imwrite,就能发现 C++ 的结果会全部黑 [因为都小于 1 了,uchar 里会变 0] ,但是 py 的会不一样。
    47jm9ozp
        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 我没怎么用过,看起来大概是隐含类型转换,除的时候给你处理成浮点了,保存时候表现不一样
    47jm9ozp
        19
    47jm9ozp  
       2019-10-16 16:30:38 +08:00
    比如这一句 r = R / (R + G + B);
    里面所有变量都是 unsigned char……
    你觉得会怎么样呢,r 中元素只可能有三个值,0/1/inf (除数为 0,可能抛异常)
    SeaRecluse
        20
    SeaRecluse  
    OP
       2019-10-16 16:31:01 +08:00
    @ooxxcc emmm 这个要双持下才会知道差别也太大了- -,我尝试手动转的代码没有贴。现在可以复现 C++下的效果,但是复现不了 Py 下的效果
    SeaRecluse
        21
    SeaRecluse  
    OP
       2019-10-16 16:32:58 +08:00
    @ooxxcc 我明白这是合理的,所以反观 py 我就懵了额。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     812 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 21:18 PVG 05:18 LAX 14:18 JFK 17:18
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86