(1)专有名词介绍
①像素和分辨率
感光元件是有很多个感光点构成的,比如有640*480个点,每个点就是一个像素,把每个点的像素收集整理起来,就是一副图片,那么这张图片的分辨率就是640480:
②帧率
帧率(FPS)就是每秒钟处理的图片数量,如果超过20帧,人眼就基本分辨不出卡顿。
③颜色、三原色
物理上,颜色就是不同波长的电磁波。但是,根据人眼的视觉效果,可以通过RGB,CMYK,HSB,LAB色域,来将可见光的颜色描述出来。
三原色的原理不是物理原因,而是由于人的生理原因造成的。人的眼睛内有几种辨别颜色的锥形感光细胞,分别对黄绿色、绿色和蓝紫色(或称紫罗兰色)的光最敏感(波长分别为564、534和420纳米)。所以RGB经常用于显示器上,用来显示图片。
④镜头的焦距
镜头焦距:是指镜头光学后主点到焦点的距离,是镜头的重要性能指标。镜头焦距的长短决定着拍摄的成像大小,视场角大小,景深大小和画面的透视强弱。当对同一距离远的同一个被摄目标拍摄时,镜头焦距长的所成的象大,镜头焦距短的所成的象小。注意焦距越长,视角越小。
(2)图像在计算机中的存储方式
在计算机中,图像是由多个像素点组成的;而图像又分为单通道图(灰度图)和多通道图(彩色图),分别用0~255表示(由暗到亮)。
对于只有黑白颜色的灰度图,为单通道,一个像素块对应矩阵中一个数字,数值为0到255, 其中0表示最暗(黑色) ,255表示最亮(白色)
对于采用RGB模式的彩色图片,为三通道图,Red、Green、Blue三原色,按不同比例相加,一个像素块对应矩阵中的一个向量, 如[24,180, 50],分别表示三种颜色的比列, 即对应深度上的数字,如下图所示:
需要注意的是,opencv采用BGR模式,而不是RGB
(3)1位~32位所表示的图像
1位:一个二进制位表示颜色,这种就叫单色显示。实例就是小饭店、理发店门口的LED屏。
8位:用8个二进制位来表示颜色,此时能表示256中颜色。这种叫灰度显示。这时候是黑白的,没有彩色。我们把纯白到纯黑分别对应表示255-0。中间的数对应不同的灰。实例就是以前的黑白电视机。
16位:用16个二进制位表示颜色,此时能表示65536种颜色。这时候就可以彩色显示了。一般采用RGB565的颜色分布(5位二进制表示红色、6位二进制表示绿色、5位二进制表示蓝色)。这种红绿蓝都有的颜色表示法就是一种模拟自然界中所有颜色的表示方式。但是因为RGB的颜色表达本身二进制位数不够多(导致红绿蓝三种颜色本身分的都不够细致),所以这样显示的彩色失真比较严重,所以人眼能明显看出显示的不真实。
24位:用24个二进制位表示颜色,能够表示16777216。这种表示方法和16位表示原理一样,只是RGB三种颜色各自的精度都更高了,RGB888。比RGB565更加真实细腻,虽然说比自然界无数种颜色还是少了很多,不过由于人眼的不理想性,人眼是感受不到这种差别,于是把RGB888的表示方法称为真彩色;RGB565位伪彩色。 32位:总共用32位二进制表示颜色,其中24位表示红绿蓝三原色,仍为RGB888,剩下的8位表示透明度。这种显色方式就叫ARGB(A为alpha,表示透明度),现在的PC中一般都是ARGB表示颜色。
import cv2 #opencv读取的格式是BGR
import matplotlib.pyplot as plt
import numpy as np
# 读取图像
img=cv2.imread('cat.jpg')
print(img)
[[[142 151 160] [146 155 164] [151 160 170] ... [156 172 185] [155 171 184] [154 170 183]]
[[108 117 126] [112 123 131] [118 127 137] ... [155 171 184] [154 170 183] [153 169 182]]
[[108 119 127] [110 123 131] [118 128 138] ... [156 169 183] [155 168 182] [154 167 181]]
...
[[162 186 198] [157 181 193] [142 166 178] ... [181 204 206] [170 193 195] [149 172 174]]
[[140 164 176] [147 171 183] [139 163 175] ... [169 187 188] [125 143 144] [106 124 125]]
[[154 178 190] [154 178 190] [121 145 157] ... [183 198 200] [128 143 145] [127 142 144]]]
由上面的输出结果可知,彩色图在计算机中是以三维数组形式存储的
cv2.IMREAD_COLOR:彩色图像
cv2.IMREAD_GRAYSCALE:灰度图像
import cv2 #opencv读取的格式是BGR
import matplotlib.pyplot as plt
import numpy as np
img=cv2.imread('cat.jpg',cv2.IMREAD_GRAYSCALE)
print(img)
[[153 157 162 ... 174 173 172] [119 124 129 ... 173 172 171] [120 124 130 ... 172 171 170] ... [187 182 167 ... 202 191 170] [165 172 164 ... 185 141 122] [179 179 146 ... 197 142 141]] 由上述输出可知,灰度图在计算机中以二维数组存储
import cv2 #opencv读取的格式是BGR
import matplotlib.pyplot as plt
import numpy as np
img=cv2.imread('cat.jpg')
#图像的显示,也可以创建多个窗口
cv2.imshow('image',img)
# ()内为等待时间,毫秒级;如果输入0则表示任意键终止
cv2.waitKey(0)
cv2.destroyAllWindows()
当需要经常进行图片的显示时,可将显示图像的三句代码封装在一个函数内:
def cv_show(name,img):
cv2.imshow(name,img)
cv2.waitKey(0)
cv2.destotyALLWindows()
其他函数:
img.shape # 若图像为彩色图像,返回值则是图像的长、宽和位深;例如返回(414,512,3)中的3表示这是一张3通道图 #若图像为二值图像,则返回值是图像的长、宽 img.dtype #返回图像的数据类型 img.size # 像素点个数 type(img) # 返回图像的存储类型
cv2.VideoCapture可以捕获摄像头,用数字来控制不同的设备,例如0,1。
如果是视频文件,直接指定好路径即可。
#视频的读取
vc=cv2.VideoCapture('test.mp4')
#利用cv2.Video.Capture来读取视频文件
#判断视频文件是否读取成功,open是一个布尔变量,open为True则表示读取到了这一帧的图像,frame是视频中读取的每一帧图像。
if vc.isOpened():
open,frame=vc.read()
else:
open = False
while open:
ret,frame=vc.read()
if frame is None:
break
if ret == True:
gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)#将彩色视频转化为灰色视频
cv2.imshow('result',gray)
if cv2.waitKey(10)&0xFF==27:#括号中数字越大,视频播放速度越慢。0xFF==27表示按ESC后退出视频播放
break
vc.release()
cv2.destoryAllWindows()
"""
:param
无
:return
无
功能:调用笔记本摄像头获取视频图片
"""""
import numpy as np
import cv2
#调用笔记本内置摄像头,所以参数为0,如果有其他的摄像头可以调整参数为1,2
cap=cv2.VideoCapture(0)
while True:
#从摄像头读取图片
sucess,img=cap.read()
#转为灰度图片
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#显示摄像头,背景是灰度。
cv2.imshow("img",gray)
#保持画面的持续。
k=cv2.waitKey(1)
if k == 27:
#通过esc键退出摄像
cv2.destroyAllWindows()
break
elif k==ord("s"):
#通过s键保存图片,并退出。
cv2.imwrite("image2.jpg",img)
cv2.destroyAllWindows()
break
#关闭摄像头
cap.release()
img=cv2.imread('cat.jpg')
cat=img[0:50,0:200]
cv_show('cat',cat)
b,g,r=cv2.split(img) # 把每个图像按照B\G\R通道进行切割,对切割出来的图像进行处理
print(r)
print(r.shape)
result: array([[160, 164, 170, ..., 185, 184, 183], [126, 131, 137, ..., 184, 183, 182], [127, 131, 138, ..., 183, 182, 181], ..., [198, 193, 178, ..., 206, 195, 174], [176, 183, 175, ..., 188, 144, 125], [190, 190, 157, ..., 200, 145, 144]], dtype=uint8) (414, 500)
img=cv2.merge((b,g,r)) # 把处理后的各通道图像合并
img.shape
(414,500,3)
# 只保留R
cur_img = img.copy()
cur_img[:,:,0] = 0
cur_img[:,:,1] = 0
cv_show('R',cur_img)
# 只保留G
cur_img = img.copy()
cur_img[:,:,0] = 0
cur_img[:,:,2] = 0
cv_show('G',cur_img)
# 只保留B
cur_img = img.copy()
cur_img[:,:,1] = 0
cur_img[:,:,2] = 0
cv_show('B',cur_img)
BORDER_REPLICATE:复制法,也就是复制最边缘像素。
BORDER_REFLECT:反射法,对感兴趣的图像中的像素在两边进行复制例如:fedcba|abcdefgh|hgfedcb
BORDER_REFLECT_101:反射法,也就是以最边缘像素为轴,对称,gfedcb|abcdefgh|gfedcba
BORDER_WRAP:外包装法cdefgh|abcdefgh|abcdefg
BORDER_CONSTANT:常量法,常数值填充
top_size,bottom_size,left_size,right_size = (50,50,50,50)
replicate = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, borderType=cv2.BORDER_REPLICATE)
reflect = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size,cv2.BORDER_REFLECT)
reflect101 = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_REFLECT_101)
wrap = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_WRAP)
constant = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size,cv2.BORDER_CONSTANT, value=0)
import matplotlib.pyplot as plt
plt.subplot(231), plt.imshow(img, 'gray'), plt.title('ORIGINAL')
plt.subplot(232), plt.imshow(replicate, 'gray'), plt.title('REPLICATE')
plt.subplot(233), plt.imshow(reflect, 'gray'), plt.title('REFLECT')
plt.subplot(234), plt.imshow(reflect101, 'gray'), plt.title('REFLECT_101')
plt.subplot(235), plt.imshow(wrap, 'gray'), plt.title('WRAP')
plt.subplot(236), plt.imshow(constant, 'gray'), plt.title('CONSTANT')
plt.show()
运行结果:
img_cat=cv2.imread('cat.jpg')
img_dog=cv2.imread('dog.jpg')
img_cat2= img_cat +10
img_cat[:5,:,0]
运行结果: array([[142, 146, 151, ..., 156, 155, 154], [108, 112, 118, ..., 155, 154, 153], [108, 110, 118, ..., 156, 155, 154], [139, 141, 148, ..., 156, 155, 154], [153, 156, 163, ..., 160, 159, 158]], dtype=uint8)
img_cat2[:5,:,0]
运行结果: array([[152, 156, 161, ..., 166, 165, 164], [118, 122, 128, ..., 165, 164, 163], [118, 120, 128, ..., 166, 165, 164], [149, 151, 158, ..., 166, 165, 164], [163, 166, 173, ..., 170, 169, 168]], dtype=uint8)
#相当于% 256
(img_cat + img_cat2)[:5,:,0]
array([[ 38, 46, 56, ..., 66, 64, 62], [226, 234, 246, ..., 64, 62, 60], [226, 230, 246, ..., 66, 64, 62], [ 32, 36, 50, ..., 66, 64, 62], [ 60, 66, 80, ..., 74, 72, 70]], dtype=uint8)
cv2.add(img_cat,img_cat2)[:5,:,0]
array([[255, 255, 255, ..., 255, 255, 255], [226, 234, 246, ..., 255, 255, 255], [226, 230, 246, ..., 255, 255, 255], [255, 255, 255, ..., 255, 255, 255], [255, 255, 255, ..., 255, 255, 255]], dtype=uint8)
9、图像融合
图像的融合并不是两者简单的相加,而是得在保证两者尺寸相同的基础上进行融合:
正确示例:
res = cv2.resize(img, (0, 0), fx=4, fy=4)
plt.imshow(res)
res = cv2.resize(img, (0, 0), fx=1, fy=3)
plt.imshow(res)