第五节:颜色通道提取,颜色通道的融合,图像融合,透视变换
(一)颜色通道提取(cv2.split)
这里需要用到cv2.split()函数,只需要传入需要分离通道的图片
import cv2
import numpy as np
img = cv2.imread("cat.jpg")
print(img.shape)
b,g,r=cv2.split(img)
print(b.shape)
print(g.shape)
print(r.shape)
cv2.imshow("img",img)
cv2.waitKey(0)
相信小伙伴们已经注意到,被分离出的b,g,r,它们都变成了单通道。这是可能会有小伙伴想,如果我们此时分别显示b,g,r,会不会分别得到原图的蓝色图,绿色图,红色图呢?试试吧
import cv2
import numpy as np
img = cv2.imread("cat.jpg")
b,g,r=cv2.split(img)
cv2.imshow("b",b)
cv2.imshow("g",g)
cv2.imshow("r",r)
cv2.waitKey(0)
是不是很意外,结果是三张灰度图,我们将RGB图像三通道拆分的过程实际上是先拆分出来,再形成了R/G/B的单通道的图像,而单通道图像就是灰度图(这就是解释,没办法,虽然有点绕,但这就是解释)。那有没有什么办法得到三通道的单独图像呢,当然有,如果想把它变成红色/绿色/蓝色的通道图,可以做通道合并(但其它通道分量为零)
import cv2
import numpy as np
img = cv2.imread("cat.jpg")
##############
R = img.copy() #复制img图片,为了避免我们改变原图的通道信息
R[:,:,0] = 0
R[:,:,1] = 0 #让图片R的B通道和G通道为0
##############
G = img.copy()
G[:,:,0] = 0
G[:,:,2] = 0 #让图片R的B通道和R通道为0
#############
B = img.copy()
B[:,:,1] = 0
B[:,:,2] = 0 #让图片R的G通道和R通道为0
#############
cv2.imshow('R',R)
cv2.imshow('G',G)
cv2.imshow('B',B)
cv2.waitKey(0)
(二)颜色通道的融合(cv2.merge)
图像通道的融合,需要用到cv2.merge()函数
看代码
import cv2
import numpy as np
img = cv2.imread("cat.jpg")
b,g,r=cv2.split(img)
img1=cv2.merge((b,g,r))
cv2.imshow("img1",img1)
cv2.waitKey(0)
我们先将原图拆分成b,g,r三个通道,然后再用cv2.merge()对图像进行合成
(三)图像融合(img1+img2,cv2.add,cv2.addWeighted)
两副图像的融合,有两种方法cv2.add与cv2.addWeighted。事实上,挖煤也可以利用numpy的数组功能,因为图像本身就是矩阵,所以我们直接将图片想加就可以得到结果(但是图片的通道和维度信息必须相同)
下面我们将直接将lena和小猫直接相加,对比几种不同的方法
我们先用numpy的数组功能,直接将图片的矩阵相加
import cv2
import numpy as np
cat=cv2.imread('cat.jpg')#(500,414,3)
lena=cv2.imread('lena.jpg')#(261,261,3)
img_cat=cat.copy()#这里我们先将小猫的图片copy一下,方便后面显示
img_cat = cv2.resize(img_cat, (263, 263))#图片的长宽信息不同,先将它们的维度统一
print(img_cat.shape)
print(lena.shape)
res=img_cat+lena
cv2.imshow("img_cat",img_cat)
cv2.imshow("lena",lena)
cv2.imshow("res",res)
cv2.waitKey(0)
结果是不是和想的不一样,因为numpy数组只是将图片相加,数值可能会超过255,因此图片显示出现了异常
再看看cv2.add()
import cv2
import numpy as np
cat=cv2.imread('cat.jpg')#(500,414,3)
lena=cv2.imread('lena.jpg')#(261,261,3)
img_cat=cat.copy()#这里我们先将小猫的图片copy一下,方便后面显示
img_cat = cv2.resize(img_cat, (263, 263))#图片的长宽信息不同,先将它们的维度统一
res=cv2.add(img_cat,lena)
cv2.imshow("img_cat",img_cat)
cv2.imshow("lena",lena)
cv2.imshow("res",res)
cv2.waitKey(0)
使用cv2.add()将两个图像相加,该函数会将图片进行截断,就是像素值相加超过255的一律取255,进行截断
我们再看看cv2.addWeighted()函数。cv2.addWeighted(img1, 0.5, img2, 0.5, 0)
第一个0.5表示第一张图片的权重,第二个0.5表示第二张图片的权重,最后的图片表示图片的重叠偏置,读者可以多试试
import cv2
import numpy as np
cat=cv2.imread('cat.jpg')#(500,414,3)
lena=cv2.imread('lena.jpg')#(261,261,3)
img_cat=cat.copy()#这里我们先将小猫的图片copy一下,方便后面显示
img_cat = cv2.resize(img_cat, (263, 263))#图片的长宽信息不同,先将它们的维度统一
res=cv2.addWeighted(img_cat,0.5,lena,0.5,0)
cv2.imshow("img_cat",img_cat)
cv2.imshow("lena",lena)
cv2.imshow("res",res)
cv2.waitKey(0)
(四)透射变换(cv2.getPerspectiveTransform,cv2.warpPerspective)
这需要使用到cv2.warpPerspective()函数,在变换前后直线还是直线。需要在原图上找到4个点,以及他们在输出图上对应的位置,这四个点中任意三个都不能共线,可以有函数cv2.getPerspectiveTransform()构建,然后这个矩阵传给函数cv2.warpPerspective()。可能你还不理解我要实现什么功能,不要急,看代码和运行结果
import cv2
import numpy as np
img = cv2.imread("page.jpg")
width,height = 500,700 #这里是预设提取出的图片大小
pts1 = np.float32([[371,351],[2153,466],[401,2985],[2365,2776]]) #这里是提取目标的四个坐标点
pts2 = np.float32([[0,0],[width,0],[0,height],[width,height]]) #这里是定义上面四个点在像新窗口中的对应位置
matrix = cv2.getPerspectiveTransform(pts1,pts2) #这里是通过cv2.getPerspectiveTransform得到变换矩阵,等一会传入cv2.warpPerspective函数
imgOutput = cv2.warpPerspective(img,matrix,(width,height))
img1=cv2.resize(img,None,fx=0.25,fy=0.25,interpolation=cv2.INTER_AREA)#应为原图太大了,所以缩小一下,对比实验结果
cv2.imshow("Image",img1)
cv2.imshow("Output",imgOutput)
cv2.waitKey(0)
不理解,看不懂?那就多看几遍,还不行,那就百度看看。你可能会问我,原图中目标的四个坐标怎么得到的,很简单,利用电脑自带的画图软件打开图片,移动鼠标到想要的位置,就能的到目标点的位置信息。你可能觉得这种方法很low,当然有更高级的方法,不要急,后面会讲到。
(五)结语
学习opencv有很多的方法,我的建议是你可以加一些群,可以充分利用B站,CSDN,和百度。
在我的博客中,我不会讲解opencv的算法实现(当然我也不太会),我只会讲解一些函数的调用,不理解就多改一些参数,多尝试尝试,慢慢你就理解来。相信你总有一天可以说opencv不过“Ctrl+C,Crtl+V”
如果有什么错误的地方,还请大家批评指正,最后,希望小伙伴们都能有所收获。