OPENCV图像处理基础
1.图像处理基础
1.1 数字图像
1.1.1 数字图像概念:
数字图像:又称数码图像,一幅二维图像可以由一个数组或矩阵表示。数字图像可以理解为一个二维函数f(x,y),其中x和y是空间(平面)坐标,而在任意坐标出的值f称为图像在该点处的强度或灰度。
图像处理的目的:改善图示的信息便于人们理解,有利于存储、传输和表示。
1.1.2 数字图像起源:
起源于20世纪20年代,媒体报纸业。
1.1.3 常见成像方式:
电磁波谱;γ射线成像;X射线成像;紫外线波段成像可见光波段成像;红外线波段成像等;
下图为X-射线成像:
1.1.4 数字图像的应用:
传统领域:医学,空间应用,生物学,军事
最新领域:数码相机,指纹识别,人脸识别,图像检索,游戏,电影特技等;
图像处理、机器视觉、人工智能关系:
图像处理主要研究二维图像,处理一个图像或一组图像之间的相互转换过程,包括图像滤波、图像识别、图像分割等;计算机视觉主要研究映射到单幅或多幅图像上的三维场景,从图像中提取抽象的语义信息,实现图像理解是计算机视觉的追求目标;人工智能在计算机视觉上的目标就是解决像素值和语义之间关系,主要的问题又图片检测、图片识别、图片分割和图片检索等。
1.1.5 Opencv介绍:
- 开源发行的跨平台计算机视觉库,是数字图像处理和计算机视觉领域非常常见的工具包
安装:打开终端/命令行cmd/虚拟环境,使用命令:pip install opencv-contrib-python 或 pip install opencv-python
如果安装失败,可先下载再使用pip命令安装,具体可参考相关教程。
1.2 图像属性
1.2.1 图像格式:
BMP格式:Windows系统下的标准位图格式,未经过压缩,一般图像文件比较大
JPEG格式:应用最广泛的格式之一,它采用一种特殊的有损压缩算法,达到较大的压缩比(可达到2:1甚至40:1)
GIF格式:可以是一张静止的图片,也可以是动画,支持透明背景图像,适用于多种操作系统,“体型”很小。但是其色域不太广,只支持256种颜色。
PNG格式:与JPG格式类似,压缩比高于GIF,支持图像透明,支持Alpha通道调节图像的透明度。
TIFF:特点是图像格式复杂,存储信息多,在Mac中广泛使用,非常有利于原稿的复制。很多地方将TIFF格式用于印刷。
注:JPEG和JPG区别可参考:https://www.zhihu.com/question/20329498。这里可理解为一个东西。
1.2.2 图像尺寸:
图像尺寸的长度和宽度以像素为单位。
像素(pixel):像素是数码影像最基本的单位,每个像素就是一个小点,不同颜色的点聚集起来即成为一幅图片。灰度像素点数值范围在0到255之间,0表示黑,255表示白,其他值表示处于黑白之间;彩色图用红、绿、蓝三通道的二维矩阵来表示。每个数值也是在0~255之间,0表示相应的基色,而255则表示相应的基色在该像素中取得最大值。
1.2.3 图像分辨率和通道:
分辨率:单位长度中的像素数目。每英寸图像中的像素点数,单位是像素每英寸(PPI)。图像分辨率越高,像素的点密度越高,图像越清晰。
通道数:图像的位深度,是指描述图像中每个pixel数值所占的二进制数。位深度越大则图像能表示的颜色数就越多,色彩越丰富逼真。
- 8位:单通道图像,也就是灰度图,灰度值范围2^8=256
- 24位:三通道3*8=24
- 32位:三通道加透明度Alpha通道
1.2.4 图像直方图:
图像直方图(Image Histogram)是用来表示数字图像中亮度分布的直方图,描绘了图像中每个亮度值的像素数。图像直方图中,横坐标左侧为纯黑、较暗的区域,右侧为较亮、纯白的区域。
图像直方图能表现出图像中的像素强度分布情况,它统计了每一个强度值所具有的像素个数。我们常借助图像直方图来实现图像的二值化。
1.2.5 图像颜色空间:
概念:一种彩色模型,用途实在某些标准下用通常可接受的方式对彩色加以说明。
常见颜色空间:RGB HSV HSI CMYK
RGB颜色空间:依据人眼识别的颜色创建,图像中每一个像素都有R,G,B三个颜色分量组成,这三个大小均为【0,255】。通常表示某个颜色的时候,写成一个3维向量的形式,如(105,123,135)。
颜色模型:归一化后,原点(0,0,0)对应黑色,距原点最远的顶点对应白色,坐标为(1,1,1);从黑色到白色的灰度值分布在这两个点的连线上,该虚线称为灰度线;立方体的其余各点对应不同的颜色,红绿蓝等等。
HSV颜色空间:根据颜色的直观特性创建的一种颜色空间。这个模型中颜色的参数分别是:色调(H),饱和度(S),明度(V)。
颜色模型:S通道,色彩/色调,代表颜色;S通道,饱和度,取值范围0%~100%,值越大颜色越饱和;V通道,明暗,数值越高越明亮,0%黑到100%白。
1.3 本章代码实现
1.读入图像
#导入opencv的python版本依赖库cv2
import cv2
#使用opencv中imread函数读取图片,
#0代表灰度图形式打开,1代表彩色形式打开
img = cv2.imread('split.jpg',1)
print(img.shape)
#print(img)
2.显示图像及保存图像(cv2和plt)
#导入opencv依赖库
import cv2
#读取图像,读取方式为彩色读取
img = cv2.imread('split.jpg',1)
#
cv2.imshow('photo',img)
k = cv2.waitKey(0)
if k == 27: # 输入ESC键退出
cv2.destroyAllWindows()
elif k == ord('s'): # 输入S键保存图片并退出
cv2.imwrite('split_.jpg',img)
cv2.destroyAllWindows()
import cv2
from matplotlib import pyplot as plt
#使用Matplotlib导入图像
img = cv2.imread('test_image.png',0)
plt.imshow(img, cmap = 'gray', interpolation = 'bicubic')
#隐藏X、Y轴上的刻度
#plt.xticks([]), plt.yticks([])
plt.show()
3.通道转化,三通道转为单通道灰度图
import cv2
#读入原始图像,使用cv2.IMREAD_UNCHANGED
img = cv2.imread("girl.jpg",cv2.IMREAD_UNCHANGED)
#查看打印图像的shape
shape = img.shape
print(shape)
#判断通道数是否为3通道或4通道
if shape[2] == 3 or shape[2] == 4 :
#将彩色图转化为单通道图
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cv2.imshow("gray_image",img_gray)
cv2.imshow("image", img)
cv2.waitKey(1000)
cv2.destroyAllWindows()
4.通道转化,单通道转为三通道灰度图
img_color = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)
5.图像通道分离与合并
import cv2 as cv
import numpy as np
src=cv.imread('split.jpg')
#cv.namedWindow('before',cv.WINDOW_NORMAL)
cv.imshow('before',src)
cv.waitKey(0)
#通道分离
b,g,r=cv.split(src)
cv.imshow('blue',b)
cv.imshow('green',g)
cv.imshow('red',r)
cv.waitKey(0)
#通道合并
#merge参数以list形式输入
src=cv.merge([b,g,r])
cv.imshow('merge',src)
cv.waitKey(0)
# 修改某个通道
src[:,:,2]=100
cv.imshow('single',src)
cv.waitKey(0)
cv.destroyAllWindows()
6.RGB转BGR
import cv2
import matplotlib.pyplot as plt
img = cv2.imread("test2.png", cv2.IMREAD_COLOR)
cv2.imshow("Opencv_win", img)
# 用opencv自带的方法转
img_cv_method = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 用numpy转,img[:,:,::-1]列左右翻转
img_numpy_method = img[:,:,::-1] # 本来是BGR 现在逆序,变成RGB
# 用matplot画图
plt.subplot(1,3,1)
plt.imshow(img_cv_method)
plt.subplot(1,3,2)
plt.imshow(img_numpy_method)
plt.subplot(1,3,3)
plt.imshow(img)
plt.savefig("./plt.png")
plt.show()
#保存图片
cv2.imwrite("opencv.png", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
7.RGB与HSV转化
import cv2
#色彩空间转换函数
def color_space_demo(image):
gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
cv2.imshow('gray',gray)
hsv=cv2.cvtColor(image,cv2.COLOR_BGR2HSV)
#print(hsv)
cv2.imshow('hsv',hsv)
#读入一张彩色图
src=cv2.imread('girl.jpg')
cv2.imshow('before',src)
#调用color_space_demo函数进行色彩空间转化
color_space_demo(src)
cv2.waitKey(0)
cv2.destroyAllWindows()
8.绘制直方图
方法一
from matplotlib import pyplot as plt
import cv2
girl = cv2.imread("girl.jpg")
cv2.imshow("girl", girl)
# girl.ravel()函数是将图像的三位数组降到一维上去,
#256为bins的数目,[0, 256]为范围
plt.hist(girl.ravel(), 256, [0, 256])
plt.show()
cv2.waitKey(0)
cv2.destroyAllWindows()
方法二
from matplotlib import pyplot as plt
import cv2
import numpy as np
img = cv2.imread('girl.jpg')
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
plt.imshow(img_gray, cmap=plt.cm.gray)
hist = cv2.calcHist([img], [0], None, [256], [0, 256])
plt.figure()
plt.title("Grayscale Histogram")
plt.xlabel("Bins")
plt.ylabel("# of Pixels")
plt.plot(hist)
plt.xlim([0, 256])
plt.show()
三通道直方图绘制
from matplotlib import pyplot as plt
import cv2
girl = cv2.imread("girl.jpg")
cv2.imshow("girl", girl)
color = ("b", "g", "r")
#使用for循环遍历color列表,enumerate枚举返回索引和值
for i, color in enumerate(color):
hist = cv2.calcHist([girl], [i], None, [256], [0, 256])
plt.title("girl")
plt.xlabel("Bins")
plt.ylabel("num of perlex")
plt.plot(hist, color = color)
plt.xlim([0, 260])
plt.show()
cv2.waitKey(0)
cv2.destroyAllWindows()
2.图像基本操作与opencv代码实现
2.1 Opencv中的绘图函数
1.线段绘制
2.矩形绘制
3.圆绘制
4.椭圆绘制
5.多边形绘制
6.添加文字
7.代码实现
import numpy as np
import cv2
# 创建一张黑色的背景图
img=np.zeros((512,512,3), np.uint8)
# 绘制一条线宽为5的线段
cv2.line(img,(0,0),(511,511),(255,0,0),1)
# 画一个绿色边框的矩形,参数2:左上角坐标,参数3:右下角坐标
cv2.rectangle(img,(384,0),(510,128),(0,255,0),3)
# 画一个填充红色的圆,参数2:圆心坐标,参数3:半径
cv2.circle(img,(447,63), 63, (0,0,255), -1)
# 在图中心画一个填充的半圆
cv2.ellipse(img, (256, 256), (100, 50), 0, 0, 180, (255, 0, 0), -1)
#绘制多边形
pts=np.array([[10,5],[20,30],[70,20],[50,10]], np.int32)
pts=pts.reshape((-1,1,2))
cv2.polylines(img,[pts], True, (0,0,255),1)
# 这里 reshape 的第一个参数为-1, 表明这一维的长度是根据后面的维度的计算出来的。
#添加文字
font=cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img,'OpenCV',(10,500), font, 4,(255,255,255),2)
winname = 'example'
cv2.namedWindow(winname)
cv2.imshow(winname, img)
cv2.waitKey(0)
cv2.destroyWindow(winname)
效果如下:
2.2 图像的几何变换
1.图像平移
将图像中所有的点按照指定的平移量水平或者垂直移动。
import cv2
import numpy as np
img = cv2.imread('img2.png')
# 构造移动矩阵H
# 在x轴方向移动多少距离,在y轴方向移动多少距离
H = np.float32([[1, 0, 50], [0, 1, 25]])
rows, cols = img.shape[:2]
print(img.shape)
print(rows, cols)
# 注意这里rows和cols需要反置,即先列后行
res = cv2.warpAffine(img, H, (2*cols, 2*rows))
cv2.imshow('origin_picture', img)
cv2.imshow('new_picture', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
2.图像缩放
下采样:缩小图像称为下采样或降采样。
上采样:放大图像称为上采样。
图像缩放是指图像大小按照指定的比例或长宽进行放大或缩小。
import cv2
import numpy as np
img = cv2.imread('img2.png')
# 方法一:通过设置缩放比例,来对图像进行放大或缩小
res1 = cv2.resize(img, None, fx=2, fy=2,
interpolation=cv2.INTER_CUBIC)
height, width = img.shape[:2]
# 方法二:直接设置图像的大小,不需要缩放因子
#cv2.INTER_NEAREST(最近邻插值) cv2.INTER_AREA (区域插值) cv2.INTER_CUBIC(三次样条插值) cv2.INTER_LANCZOS4(Lanczos插值)
res2 = cv2.resize(img, (int(0.8*width), int(0.8*height)),interpolation=cv2.INTER_LANCZOS4)
cv2.imshow('origin_picture', img)
#|cv2.imshow('res1', res1)
cv2.imshow('res2', res2)
cv2.waitKey(0)
cv2.destroyAllWindows()
3.图像旋转
根据图像的旋转中心,将图像旋转一定的角度。旋转后图像的大小一般会改变,即可以把转出显示区域的图像截去,或者扩大图像范围来显示所有的图像。图像的旋转变换也可以用矩阵变换来表示。
设点p0(x,y)逆时针旋转θ角后的对应坐标为p(x,y),则p(x,y)为:
为避免信息的丢失,图像平移前应有一定的坐标平移。图像旋转后,会出现许多空洞点,对这些点需要进行填充处理。
import cv2
import numpy as np
img=cv2.imread('img2.png',1)
rows,cols=img.shape[:2]
#参数1:旋转中心,参数2:旋转角度,参数3:缩放因子
#参数3正为逆时针,负值为正时针
M=cv2.getRotationMatrix2D((cols/2,rows/2),45,1,)
print(M)
#第三个参数是输出图像的尺寸中心
dst=cv2.warpAffine(img,M,(cols,rows))
#borderValue为填充值
#dst=cv2.warpAffine(img,M,(cols,rows),borderValue=(255,255,255))
while(1):
cv2.imshow('img', img)
cv2.imshow('img1',dst)
#0xFF==27 ESC
if cv2.waitKey(1)&0xFF==27:
break
cv2.destroyAllWindows()
4.仿射变换
仿射变换是对图像进行旋转、平移、缩放等操作以达到数据增强的效果。
特点:变换前是直线,变换后依然是直线;直线的比例保持不变。
import cv2
import numpy as np
import matplotlib.pyplot as plt
#读取图片
src = cv2.imread('bird.png')
#获取图像大小
rows, cols = src.shape[:2]
#设置图像仿射变换矩阵
pos1 = np.float32([[50,50], [200,50], [50,200]])
pos2 = np.float32([[10,100], [200,50], [100,250]])
M = cv2.getAffineTransform(pos1, pos2)
print(M)
#图像仿射变换
result = cv2.warpAffine(src, M, (2*cols, 2*rows))
#显示图像
cv2.imshow("original", src)
cv2.imshow("result", result)
#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()
5.透视变化
将图像投影到一个新的视平面。
import cv2
import numpy as np
import matplotlib.pyplot as plt
#读取图片
src = cv2.imread('bird.png')
#获取图像大小
rows, cols = src.shape[:2]
#设置图像透视变换矩阵
pos1 = np.float32([[114, 82], [287, 156],
[8, 100], [143, 177]])
pos2 = np.float32([[0, 0], [188, 0],
[0, 262], [188, 262]])
M = cv2.getPerspectiveTransform(pos1, pos2)
#图像透视变换
result = cv2.warpPerspective(src, M, (2*cols,2*rows))
#显示图像
cv2.imshow("original", src)
cv2.imshow("result", result)
#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()
6.文档