一个简单的图片像素操作

opencv 置为黑色 opencv黑白色反转_色彩空间

 

这个是实现了一个底片效果的代码,其实很简单,就是每个点的像素都用255减去它就可以了,上面我为了避免用三循环,直接利用ndarray广播机制了,非常的方便。还有一种办法,仔细想一想用255减去某一个值,是不是相当于取反呢?0xFF-a其实就相当于是对a取反,因为0取反是1,1取反是0,0+1=1。

opencv 置为黑色 opencv黑白色反转_opencv_02

 

时间其实都挺快的。单位是秒。

生成自己的图片

我们也只是简单生成一些颜色图片而已。

opencv 置为黑色 opencv黑白色反转_opencv 置为黑色_03

 

这是一张黑色的图。

opencv 置为黑色 opencv黑白色反转_灰度图_04

 

这是白色的图。这里都是三通道的BGR模式。那么可以生成某一种非黑白颜色的嘛?

我们尝试几个。首先是蓝色。蓝色要求B通道是255,GR都是0。

opencv 置为黑色 opencv黑白色反转_MATLAB_05

 

这个255也会广播的,别说,我发现numpy数组的广播机制还是挺好用的。

opencv 置为黑色 opencv黑白色反转_opencv 置为黑色_06

 

 

opencv 置为黑色 opencv黑白色反转_色彩空间_07

 

MATLAB的加减是有广播的,但是乘除没有,因为乘除都是由矩阵运算的含义,那么点乘,点除呢?所谓点乘,点除也是元素运算。

opencv 置为黑色 opencv黑白色反转_MATLAB_08

 

看来是我对MATLAB不够了解,MATLAB的点乘也是有广播机制的,以前我都不知道。

然后是绿色。

opencv 置为黑色 opencv黑白色反转_灰度图_09

 

再来试一个紫色。

opencv 置为黑色 opencv黑白色反转_opencv 置为黑色_10

 

 

opencv 置为黑色 opencv黑白色反转_opencv_11

 

enmm,好像有点差别,这是因为dtype选择的不恰当,上面看到有小数点,应该是浮点数类型,前面我演示过数据类型不合适导致的数据异常,我们还是选一个uint8比较合适。

opencv 置为黑色 opencv黑白色反转_opencv_12

 

这个颜色就对了。不过上面都是BGR的,我们再来试一试灰度图,灰度图只有一个通道。

opencv 置为黑色 opencv黑白色反转_灰度图_13

 

首先没有2通道,只有1,3,4个通道是加了一个A,alpha,叫做透明度。

opencv 置为黑色 opencv黑白色反转_opencv_14

 

0是黑色。

opencv 置为黑色 opencv黑白色反转_opencv_15

 

 

opencv 置为黑色 opencv黑白色反转_opencv_16

 

 

opencv 置为黑色 opencv黑白色反转_opencv_17

 

还是要注意dtype。

色彩空间及其转换

opencv默认的色彩空间是BGR,0-255是亮度值。

opencv 置为黑色 opencv黑白色反转_灰度图_18

 

 

opencv 置为黑色 opencv黑白色反转_opencv 置为黑色_19

 

RGB还有很多格式:

opencv 置为黑色 opencv黑白色反转_MATLAB_20

 

我们这里用得就是RGB24。

opencv 置为黑色 opencv黑白色反转_opencv_21

 

不过我们提供了API可以使色彩空间相互转化。

opencv 置为黑色 opencv黑白色反转_色彩空间_22

 

RGB转灰度是我们已经见过的,不过其实也有很多算法,参考:

上面还有几个我们没有见过的。下面一个一个来认识。先来看HSV色彩空间。参考了

opencv 置为黑色 opencv黑白色反转_opencv 置为黑色_23

 

 

opencv 置为黑色 opencv黑白色反转_灰度图_24

 

 

opencv 置为黑色 opencv黑白色反转_色彩空间_25

 

关于互补色:

opencv 置为黑色 opencv黑白色反转_opencv 置为黑色_26

 

转换的公式,参考了:

opencv 置为黑色 opencv黑白色反转_色彩空间_27

 

 

opencv 置为黑色 opencv黑白色反转_色彩空间_28

 

转换表:

opencv 置为黑色 opencv黑白色反转_灰度图_29

 

 

opencv 置为黑色 opencv黑白色反转_MATLAB_30

 

转换算法,我们用的多的是RGB到HSV。

opencv 置为黑色 opencv黑白色反转_opencv 置为黑色_31

 

这个算法出来的结果H在0-360,S在0-1,V在0-255之间,不过上面的表格里面,H在0-180之间,S和V都在0-255,这个也不难转换一下就可以了,S乘个255,H除以一个2。H在0-180之间的原因可能是可以用一个字节存得下。

opencv 置为黑色 opencv黑白色反转_opencv_32

 

那么先来尝试一下转换吧。

opencv 置为黑色 opencv黑白色反转_色彩空间_33

 

这个报错的原因还是dtype。这里先插播一条消息:

opencv 置为黑色 opencv黑白色反转_色彩空间_34

 

没错,MATLAB里也有这个东西,感觉MATLAB还是挺强大的啊。

opencv 置为黑色 opencv黑白色反转_MATLAB_35

 

标题乱码是因为编码问题。这个sublime里面有菜单可以选,除此以外还有很多方式,可以参考

重点关注转换的结果,本来是蓝色,BGR是(255,0,0)根据上面的表格,转化之后的HSV结果是(240,1,1)在做一些处理,就变成了(120,255,255)转换的结果是对的,但是为什么显示出来不对呢?这是因为imshow还是按照BGR来显示的,所以出来不是蓝色:

opencv 置为黑色 opencv黑白色反转_色彩空间_36

 

HSL也叫HLS,参考了

opencv 置为黑色 opencv黑白色反转_MATLAB_37

 

 

opencv 置为黑色 opencv黑白色反转_灰度图_38

 

 

opencv 置为黑色 opencv黑白色反转_灰度图_39

 

 

opencv 置为黑色 opencv黑白色反转_opencv 置为黑色_40

 

这个上面也有转换函数,我们也不去试了,我们主要是了解这些色彩空间,转换太简单了,一个函数就完事了。

其它色彩空间参考了:

opencv 置为黑色 opencv黑白色反转_色彩空间_41

 

YUV也有很多格式,

opencv 置为黑色 opencv黑白色反转_opencv 置为黑色_42

 

参考

opencv 置为黑色 opencv黑白色反转_色彩空间_43

 

这些有需要的可以自己深入去了解,有的时候我们需要按需求来学习知识。

opencv 置为黑色 opencv黑白色反转_MATLAB_44

 

在人脸检测中也常常用到YCrCb空间,因为一般的图像都是基于RGB空间的,在RGB空间里人脸的肤色受亮度影响相当大,所以肤色点很难从非肤色点中分离出来,也就是说在此空间经过处理后,肤色点是离散的点,中间嵌有很多非肤色,这为肤色区域标定(人脸标定、眼睛等)带来了难题。如果把RGB转为YCrCb空间的话,可以忽略Y(亮度)的影响,因为该空间受亮度影响很小,肤色会产生很好的类聚。这样就把三维的空间降为二维的CrCb,肤色点会形成一定得形状,如:人脸的话会看到一个人脸的区域,手臂的话会看到一条手臂的形态,对处理模式识别很有好处,根据经验某点的CrCb值满足:133≤Cr≤173,77≤Cb≤127 那么该点被认为是肤色点,其他的就为非肤色点。C代表color,r代表红色,b代表蓝色。

opencv 置为黑色 opencv黑白色反转_色彩空间_45

 

 

opencv 置为黑色 opencv黑白色反转_opencv 置为黑色_46

 

当然色彩空间不止这么几种,其它的我们用到的时候再补充一下。

色彩捕捉

色彩捕捉需要用到一个cv2的函数,叫做inRange。

opencv 置为黑色 opencv黑白色反转_opencv 置为黑色_47

 

src是输入的数组,lowerb是lower boundary,就下界,upperb是上界,dst是输出。dst有一个规则就是如果在这个范围内,这个像素点位置的值就设为255,不在范围内就设置为0。scalar这个词经常看到,时标量的意思。可以看一看

opencv 置为黑色 opencv黑白色反转_MATLAB_48

 

参数4我们用不到,这个操作也可以叫做二值化,顾名思义,就所有的数非0就是255。参考

opencv 置为黑色 opencv黑白色反转_opencv_49

 

CV_8U就是无符号的八位二进制数。我们来捕捉一下黑色。按照下面的经验表来确定上下界。

opencv 置为黑色 opencv黑白色反转_MATLAB_50

 

 

opencv 置为黑色 opencv黑白色反转_opencv 置为黑色_51

 

这个是原图。

opencv 置为黑色 opencv黑白色反转_色彩空间_52

 

并且看到二值化之后其实就是灰度图了,只有一个通道。这是二值化的结果:

opencv 置为黑色 opencv黑白色反转_opencv_53

 

黑色的地方全部被刷成白色,因为灰度图里面255是白色。但是看到由于头发上面有一些反光,黑的不是那么彻底,就不在我们的范围里面了,我们可以改这个范围。我把v的范围调大了一些,头发那里虽然好了一些,但是其它不是那么黑的地方就也在范围里面了,不过我设置一下把在范围里面的设置为黑色,这个非一下就行。这个效果还可以。

opencv 置为黑色 opencv黑白色反转_灰度图_54

 

但是我就在想,为什么不能直接在BGR模式下做这个inRange呢?必须在HSV模式下吗?

opencv 置为黑色 opencv黑白色反转_色彩空间_55

 

这个是在BGR直接用inRange的,看起来效果也还可以啊。可能是我们的要求不太高吧。

用threshold也能实现二值化:

opencv 置为黑色 opencv黑白色反转_色彩空间_56

 

 

opencv 置为黑色 opencv黑白色反转_灰度图_57

 

这个明显没有inRange好用,如果我们自己要写一个inRange,要有三个循环,有点麻烦。

我们来捕捉一下蓝色。原图:

opencv 置为黑色 opencv黑白色反转_灰度图_58

 

 

opencv 置为黑色 opencv黑白色反转_灰度图_59

 

效果还不错。下面是用BGR,现在我体会到HSV比较好的一点是,有经验值,下面的值是我自己定的,必须得接近纯蓝才会被识别。

opencv 置为黑色 opencv黑白色反转_灰度图_60

 

通道的拆分和融合

这个可能有时候用到,拆分我们可以有很多种方式。

切片是一种方式。

opencv 置为黑色 opencv黑白色反转_色彩空间_61

 

可以用stack来融合。

opencv 置为黑色 opencv黑白色反转_色彩空间_62

 

和原来的是一样的。opencv还提供了专门的API,分别是cv2.split和cv2.merge。

opencv 置为黑色 opencv黑白色反转_MATLAB_63

 

 

opencv 置为黑色 opencv黑白色反转_opencv_64

 

那么就先到这里。