一起学python-opencv五(回归opencv的一些实验,色彩空间及其转换和色彩捕捉)

版权声明: https://blog.csdn.net/qq_41740705/article/details/82759597

一个简单的图片像素操作

 

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

 

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

生成自己的图片

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

 

这是一张黑色的图。

 

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

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

 

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

 

 

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

 

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

然后是绿色。

 

再来试一个紫色。

 

 

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

 

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

 

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

 

0是黑色。

 

 

 

还是要注意dtype。

色彩空间及其转换

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

 

 

RGB还有很多格式:

 

我们这里用得就是RGB24。

 

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

 

RGB转灰度是我们已经见过的,不过其实也有很多算法,参考:https://blog.csdn.net/xdrt81y/article/details/8289963

上面还有几个我们没有见过的。下面一个一个来认识。先来看HSV色彩空间。参考了https://blog.csdn.net/u010429424/article/details/76577399

 

 

 

关于互补色:

 

转换的公式,参考了:https://www.cnblogs.com/klchang/p/6784856.html

 

 

转换表:

 

 

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

 

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

 

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

 

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

 

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

 

标题乱码是因为编码问题。这个sublime里面有菜单可以选,除此以外还有很多方式,可以参考https://blog.csdn.net/u010412833/article/details/73649610

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

 

HSL也叫HLS,参考了https://blog.csdn.net/zhangping1987/article/details/73699335

https://blog.csdn.net/jiangxinyu/article/details/8000999

 

 

 

 

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

其它色彩空间参考了:

https://blog.csdn.net/Solomon1558/article/details/43772147

 

YUV也有很多格式,

 

参考https://www.cnblogs.com/ALittleDust/p/5935983.html

 

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

 

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

 

 

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

色彩捕捉

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

 

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

 

参数4我们用不到,这个操作也可以叫做二值化,顾名思义,就所有的数非0就是255。参考https://blog.csdn.net/zxjor91/article/details/46584871

 

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

 

 

这个是原图。

 

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

 

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

 

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

 

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

用threshold也能实现二值化:

 

 

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

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

 

 

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

 

通道的拆分和融合

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

切片是一种方式。

 

可以用stack来融合。

 

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

 

 

那么就先到这里。

猜你喜欢

转载自blog.csdn.net/qq_41740705/article/details/82759597