文章目录
1.数字图像基本概念
1.1 数字图像概念
数字图像,又称数码图像或数位图像,是二维图像用有限数字数值像素的表示。由数组或矩阵表示,其光照位置和强度都是离散的。数字图像是由模拟图像数字化得到的、以像素为基本元素的、可以用数字计算机或数字电路存储和处理的图像。
1.2像素概念
像素是数字图像的基本元素,像素是在模拟图像数字化时对连续空间进行离散化得到的。每个像素具有整数行(高)和列(宽)位置坐标,同时每个像素都具有整数灰度值或颜色值。
1.3图像种类
根据采样数目及特性的不同数字图像主要可以分为以下几类:
1.3.1 二值图像
图像中每个像素亮度值仅可以取0到1的图像
1.3.2 灰度图像
图像中每个像素可以由0(黑)到255(白)的亮度值表示,0-255之间表示不同的灰度级
1.3.3 彩色图像
每幅彩色图像是由三幅不同颜色的灰度图像叠加而成:分别为B(蓝色)、G(绿色)、R(红色),也就是对于每个彩色图像,其每个像素由(B,G,R)的一个tuple组成,(0,0,0)表示黑色,(255,255,255)表示白色
2.图像操作
理解了数字图像的概念,我们可以进一步针对图像进行操作。
2.1 查看图像属性
我们可以执行以下操作查看图片本身的属性:
#img_1即为笔记(一)种我们导入的图片
print("img_1's dimensions:",img_1.ndim)#维数
print("img_1's shape:",img_1.shape)#形状
print("img_1's size:",img_1.size)#大小
print("img_1's dtype:",img_1.dtype)
结果如下:
我们可以看到图像的维度为3,这是因为我们导入的彩色图像。形状为(1080,2310,3),这说明宽度方向有1080个像素,长度方向有2310个。而
1080
×
2310
×
3
=
748440
1080\times2310\times3 = 748440
1080×2310×3=748440,从而图像对应数组大小为748440。
知道上述信息以后,我们可以进行更多操作例如查看一点像素值:
print(img_1[540,1155])#查看中心点像素值
结果为:[164,82,51]
2.2 图像扩边
给图形添加边框我们可以使用copyMakeBorder函数:
img_1 = cv.copyMakeBorder(img_1,10,10,10,10,cv.BORDER_CONSTANT,value=(255,0,255))
函数中各个参数意义解释如下:
1.添加边框对象
2.top,bottom,left,right为四个对应位置边框宽度
3.边框类型,有以下几种类型可以选择:BORDER_CONSTANT、BORDER_DEFAULT、BORDER_ISOLATED、BORDER_REFLECT、BORDER_REFLECT_101、BORDER_REFLECT101、BORDER_REPLICATE、BORDER_TRANSPARENT、BORDER_WRAP对于每种类型的样式大家可以自己尝试
4.value,当边框类型选择BORDER_CONSTANT时,需要此参数,作用为指定边框颜色。
2.3 裁剪、更改图像
将部分像素取出来我们可以裁剪出想要的部分:
img_1_1 = img_1[100:200,500:600]
cv.imshow('picture1_1',cv.resize(img_1_1,(400,400)))#opencv本身的resize函数也可以更改图像大小
运行结果如下:
我们可以对原图像中的区域做颜色更改:
for i in range(500,701):
for j in range(500,701):
img_1[i,j] = [i,j,i+j]#此时的加法结果会对255取模
cv.imshow('picture1_2',it.resize(img_1,800))
结果如下:
可见图中(500,500)至(700,700)的方形区域被我们更改了颜色。
2.4 图像融合
图像融合函数addWeighted函数可以帮助我们实现两幅图像的融合,但是是有条件的,这两幅图像的分辨率应相同,也就是形状大小等属性应该相同。我们将以下两幅图像融合起来:
语句为:
img = cv.addWeighted(img_1,0.6,img_4,0.4,0)#第二张图片为img_4
函数的形式如下:
cv2.addWeighted(InputArray src1, double alpha, InputArray src2, double beta, double gamma, OutputArray dst, int dtype=-1)
参数意义:
1.第一个对象
2.第一个对象占权重
α
\alpha
α
3.第二个对象
4.第二个对象占权重
β
(
=
1
−
α
)
\beta(=1-\alpha)
β(=1−α)
5.加权后图像的偏移量
γ
\gamma
γ
6.输出的数组
7.输出阵列的深度
一般我们使用前五个变量即可,后两个有默认值
例子中
γ
\gamma
γ取值为0,融合后的图像如下:
γ
\gamma
γ改为100时,图像如下:
可以看到其变白了,当
γ
\gamma
γ取到255时,输出图像就变为纯白色了。
2.5 转换图像空间
#图像色彩空间变换函数
cv.cvtColor(src,code)
一般我们传递两个参数即可,第一个参数为转换对象,第二个参数为变换类型,类型有很多种,大家可以执行一下代码查看全部类型:
import cv2
flags = [i for i in dir(cv2) if i.startswith('COLOR_')]
print(flags)
其中最最常用的类型为将图像从BGR彩色图转换为灰度图:
img = cv.cvtColor(img_1,cv.COLOR_BGR2GRAY)
输出图像为:
函数还可将图像转换为HSV空间等,大家可以自行根据需要尝试。
3.基本绘图操作
opencv提供了绘制图形的函数,我们做一基本介绍。
3.1 绘制直线
一般绘制直线的命令为:
cv.line(img,pt1,pt2,color,thickness = None,lineType = None)
参数意义为:
1.进行绘制的图像对象
2.直线起点像素坐标
3.直线终点像素坐标
4.颜色,用(B,G,R)表示
5.线宽与线型,有默认值
3.2 绘制矩形
一般绘制矩形的命令为:
cv.rectangle(img,pt1,pt2,color,thickness = None,lineType = None)
pt1,pt2为矩形左上角像素坐标与右下角像素坐标,其他参数与绘制直线相同(以下称为公共参数)。
3.3 绘制圆
一般绘制圆的命令为:
cv.circle(img,center,radius,color,thickness = None,lineType = None)
center为圆心像素坐标,radius为半径长度,其他为公共参数,需要指出的是,当thickness=-1时,绘制实心圆;为正数时,绘制空心圆
3.4 绘制椭圆
一般绘制椭圆的命令为:
cv.ellipse(img,center,axes,angle,startAngle,endAngle,color,thickness = None,lineType = None)
center为中心像素坐标,axes为(长轴长度,短轴长度),angle为绕中心旋转角度,startAngle与endAngle分别为从主轴沿顺时针方向测量的椭圆起始与终止角度,thickness的取值与圆相同,其余为公共参数
3.5 绘制多边形
一般绘制多边形的命令为:
cv.polylines(img,pts,isClosed,color,thickness = None,lineType = None)
pts为多边形点的集合,可以用numpy.array定义。isClosed可选择True或者False,前者表示封闭,后者表示不封闭(即最后一个点是否与第一个点相连),其余为公共参数
3.6 示例
以上几种绘图操作的完整代码示例:
import cv2 as cv
import imutils as it
import numpy as np
img_1 = cv.imread('D:/programming/Python learn/PythonApplication1/pic_1.jpg')
img_1 = cv.line(img_1,(100,200),(300,500),(100,200,250),5)
img_1 = cv.rectangle(img_1,(100,200),(300,500),(0,255,0),3)
img_1 = cv.circle(img_1,(800,800),100,(0,0,255),-1)
img_1 = cv.circle(img_1,(600,400),50,(255,0,0),5)
img_1 = cv.ellipse(img_1,(1155,540),(500,250),30,0,180,(50,100,150),8)
pts = np.array([[100,100],[300,450],[280,670],[1000,900]],np.int32)
img_1 = cv.polylines(img_1,[pts],True,(255,0,255),7)
cv.imshow('draw',it.resize(img_1,800))
if cv.waitKey(-1)==ord('A'):
cv.destroyAllWindows()
结果为: