对于只有黑白颜色的灰度图,为单通道,一个像素块对应矩阵中一个数字,数值为0到255, 其中0表示最暗(黑色) ,255表示最亮(白色)。
对于任何一张彩色图片,有三个主通道–RGB(红绿蓝)。按不同比例相加,一个像素块对应矩阵中的一个向量, 如[24,180, 50],分别表示三种颜色的比列, 即对应深度上的数字。图片的大小为(height,width,3)。
注:opencv采用BGR模式,而不是RGB。
RGB 由三个通道表示一幅图像,分别为红色( R),绿色(G)和蓝色(B)。RGB 颜色空间利用三个颜色分量的线性组合来表示颜色,任何颜色都与这三个分量有关,而且这三个分量是高度相关的,所以连续变换颜色时并不直观,想对图像的颜色进行调整需要更改这三个分量才行。三种颜色的取值范围均为[0,255]。
2.HSV- 在图像处理中使用较多的是HSV颜色空间,它比 RGB 更接近人们对彩色的感知经验。非常直观地表达颜色的色调、鲜艳程度和明暗程度,方便进行颜色的对比,常用于分割指定颜色的物体。
- HSV 表达彩色图像的方式由三个部分组成:Hue(色调、色相);Saturation(饱和度、色彩纯净度);Value(明度)
- 用下面这个圆柱体来表示 HSV 颜色空间,圆柱体的横截面可以看做是一个极坐标系 ,H 用极坐标的极角表示,S 用极坐标的极轴长度表示,V 用圆柱中轴的高度表示。
Hue 用角度度量,取值范围为0~360°,表示色彩信息,即所处的光谱颜色的位置。颜色圆环上所有的颜色都是光谱上的颜色,从红色开始按逆时针方向旋转,Hue=0 表示红色,Hue=120 表示绿色,Hue=240 表示蓝色。
(2)Saturation(饱和度、色彩纯净度)- 其中水平方向表示饱和度,饱和度表示颜色接近光谱色的程度。饱和度越高,说明颜色越深,越接近光谱色。饱和度越低,说明颜色越浅,越接近白色。饱和度为0表示纯白色。取值范围为0~100%,值越大,颜色越饱和。
- 在Hue一定的情况下,饱和度减小,就是往光谱色中添加白色,光谱色所占的比例也在减小,饱和度减为0,表示光谱色所占的比例为零,导致整个颜色呈现白色。
- 竖直方向表示明度,决定颜色空间中颜色的明暗程度,明度越高,表示颜色越明亮,范围是 0-100%。明度为0表示纯黑色(此时颜色最暗)。
- 明度减小,就是往光谱色中添加黑色,光谱色所占的比例也在减小,明度减为0,表示光谱色所占的比例为零,导致整个颜色呈现黑色。
H:0-180
S:0-255
V:0-255
颜色的模糊范围:
import cv2 ## 导入OpenCV库(2)加载图片
cv2.imread(filename,[flags])
- filename:图片的路径,即使路径错误也不会报错,但打印返回的图片对象为None
- flags:cv2.IMREAD_COLOR,读取彩色图片,图片透明性会被忽略,为默认参数,也可以传入1;
cv2.IMREAD_GRAYSCALE,按灰度模式读取图像,也可以传入0
cv2.IMREAD_UNCHANGED,读取图像,包括其alpha通道,也可以传入-1
img_ty = cv2.imread('ty.jpg',1) ## 加载图片名称为ty.jpg的彩色图片2.查看图片信息 (1)查看图片性质
- img.shape :输出图片的形状,图片的形状指的是一个NumPy数组。若该图片是一个彩色图片,则输出一个三维数组,(高度,宽度,通道数);若为黑白图片,则输出一个二维数组,(高度,宽度)。
- img.size:返回所有像素数量,=高度宽度通道数。
- img.dtype:返回数组类型。
import cv2 img_ty = cv2.imread('ty.jpy') ## 输出图片的形状 print(img_ty.shape) ## 输出ty.jpg图片的大小 ##Out[1]: (854, 740, 3) print(img_ty.size) ##Out[2]: 1895880 print(img_ty.dtype) ##Out[3]: uint8(2)获取和编辑图像像素 1° 获取图像像素
## 1.切片 pixel = img[100,100] ## 获取(100,100)处的像素值 print(pixel) ##Out[1]: [ 70 176 230] b = img_ty[100,100,0] ## 获取(100,100)处,blue通道像素值 print(b) ##Out[2]: 70 ## 2.item r = img_ty.item(100,100,2) print(r) ##Out[3]: 2302° 编辑图像像素
## 1.切片 img_ty[100,100,2] = 99 ## 设置red通道值 print(img_ty[100,100]) ##Out[1]: [ 70 176 99] ## 2.itemset img_ty.itemset((100,100,1),99) print(img_ty[100,100]) ##Out[2]: [ 70 99 99]3° 图片截取
## 1.通道截取 b = img_ty[:,:,0] #截取整个蓝色通道 b,g,r = cv2.split(img) ## 截取三个通道,比较耗时 img = cv2.merge((b,g,r)) ## 通道合并 ## 2.区域截取 roi = img[100:200,300:400] ## 截取100行到200行,列为300到400列的整块区域 img[50:150,200:300] = roi ## 将截取的roi移动到该区域 (50到100行,200到300列)3.显示图片 (1)cv2.imshow(winname, mat)
第一个参数表示输出窗口的窗口名称,第二个参数表示要显示的图像。
注:可以创建任意数量的窗口,但必须使用不同的窗口名称。
- waitKey控制着imshow的持续时间,当imshow之后不跟waitkey时,相当于没有给imshow提供时间展示图像,所以有一个空窗口一闪而过或者出现未响应情况。
- cv2.waitKey()是一个键盘绑定函数。它的时间量度是毫秒ms。函数会等待(n)里面的n毫秒,看是否有键盘输入。若有键盘输入,则返回按键的ASCII值。没有键盘输入,则返回-1.一般设置为0,他将无限等待键盘的输入。
cv2.destroyAllWindows() 用来删除所有窗口
cv2.destroyWindow(winname):删除特定的窗口
cv2.imshow('ty',img_ty) ## 在一个名为ty的窗口显示图片ty.jpg cv2.waitKey(0) ## 让窗口持续显示 cv2.destroyAllWindows() ## 删除窗口 ## cv2.destroyWindow('ty')4.调整图像大小
cv2.resize(InputArray src, OutputArray dst, Size, fx, fy, interpolation)
参数解释:
interpolation 选项所用的插值方法:
cv2.imwrite(img_path_name,img):第一个参数为保存的文件名,第二个参数为文件对象。
6.实例import cv2 img_ty = cv2.imread('ty.jpg',1) ## 将图片高和宽分别赋值给x,y x,y = img_ty.shape[0:2] ## 如果输出空格则关闭ty1窗口 cv2.imshow('ty1',img_ty) dt = cv2.waitKey(0) if dt == 32: cv2.destroyWindow('ty1') ## 缩放到原来的二分之一,输出尺寸格式为(宽,高) img_ty2 = cv2.resize(img_ty, (int(y / 2), int(x / 2))) cv2.imshow('ty2', img_ty2) cv2.waitKey(0) # 缩放到原来的四分之一 img_ty3 = cv2.resize(img_ty, (0, 0), fx=0.25, fy=0.25, interpolation=cv2.INTER_NEAREST) cv2.imshow('ty3', img_ty3) cv2.waitKey(0) cv2.destroyAllWindows() cv2.imwrite('ty_copy.jpg',img_ty)
cv2.copyMakeBorder(src,top, bottom, left, right ,borderType,value)
参数解释:
- src:原图像
- top,bottem,left,right:分别表示四个方向上边界的长度
- borderType:边界的类型
- value:如果borderType为cv2.BORDER_CONSTANT时需要填充的常数值
import cv2 import numpy as np import matplotlib.pyplot as plt img = cv2.imread('sugar.jpg') ## 画图 def draw_img(i,img,title): plt.subplot(2,3,i) plt.imshow(img) plt.axis('off') plt.title(title) ## BGR转RGB img_rgb = cv2.cvtColor(img_rgb,cv2.COLOR_BGR2RGB) ## 边界填充 constant = cv2.copyMakeBorder(img_rgb, 100, 100, 100, 100, cv2.BORDER_CONSTANT, value=[255, 0, 0]) reflect = cv2.copyMakeBorder(img_rgb, 100, 100, 100, 100, cv2.BORDER_REFLECT) default = cv2.copyMakeBorder(img_rgb, 100, 100, 100, 100, cv2.BORDER_DEFAULT) replicate = cv2.copyMakeBorder(img_rgb, 100, 100, 100, 100, cv2.BORDER_REPLICATE) wrap = cv2.copyMakeBorder(img_rgb, 100, 100, 100, 100, cv2.BORDER_WRAP) ## 画图 draw_img(1,img_rgb,'original') draw_img(2,constant,'constant') draw_img(3,reflect,'reflect') draw_img(4,default,'default') draw_img(5,replicate,'replicate') draw_img(6,wrap,'wrap') plt.show()2.色彩模式转换 (1)cv2.cvtColor()
使用cv2.cvtColor()函数实现色彩空间的变换,该函数可以实现多个色彩空间之间的转换。
dst = cv2.cvtColor(src,code,[dstCn])
- src:表示原图。
- code:色彩空间转换码。
- dstCn:目标图像的通道数,默认为0,通道自动通过原图和code获得。
使用以下命令可获得code参数:
import cv2 import numpy as np flags = [i for i in dir(cv2) if i.startswith('COLOR_')] print(flags) ## 输出一大串
经常使用的code参数:
import cv2 import matplotlib.pyplot as plt ## 画图 def show_im(num,img,title): plt.subplot(2,2,num) plt.imshow(img) plt.axis('off') plt.title(title) ## 显示读取的图片 img_BGR = cv2.imread('ty.jpg',1) show_im(1,img_BGR,'BGR') ## 将图片转为RGB图 img_RGB = cv2.cvtColor(img_BGR,cv2.COLOR_BGR2RGB) show_im(2,img_RGB,'RGB') ## 将图片转为灰度图 img_GRAY = cv2.cvtColor(img_BGR,cv2.COLOR_BGR2GRAY) show_im(3,img_GRAY,'GRAY') ## 将图片转为HSV img_HSV = cv2.cvtColor(img_BGR,cv2.COLOR_BGR2HSV) show_im(4,img_HSV,'HSV') plt.savefig('ty_conbine.jpg') plt.show()(2)cv2.inRange()
使用inRange函数设阈值。
dst = cv2.inRange(src, lowerb, upperb, dst=None)
- src:表示原图。
- lowerb:表示阈值下限。
- upperb:表示阈值上限。
- dst:输出和src相同的矩阵。
用OpenCV处理图像时,获得的矩阵类型都是uint8。uint8是专门用于存储各种图像的(包括RGB,灰度图像等),范围是从0–255。要想将当前的数组作为图像类型来进行各种 *** 作,就要转换到uint8类型。
import numpy as np a = [245,100,2] np.uint8(a) ##Out[1]: array([245, 100, 2], dtype=uint8)(4)实例
在OpenCV中HSV三个分量的范围为:H = [0,179] S = [0,255] V = [0,255]
1° BGR转换HSVimport numpy as np import cv2 bgr_blue = np.uint8([[[255,0,0]]]) hsv_blue = cv2.cvtColor(bgr_blue, cv2.COLOR_BGR2HSV) print(hsv_blue) ## Out[1]: array([[[120, 255, 255]]], dtype=uint8)2° 提取特征颜色
因为H=0和H=180都对应红色,所以对于红色的话,需要定义两个范围,并进行取或 *** 作。
import numpy as np import cv2 import matplotlib.pyplot as plt ## 画图 def show_im(num,img,title): plt.subplot(1,2,num) plt.imshow(img) plt.axis('off') plt.title(title) ## 读取图片 ty_img = cv2.imread('ty_red.jpg') ## 显示原图(转换为rgb正常格式) ty_rgb = cv2.cvtColor(ty_img, cv2.COLOR_BGR2RGB) show_im(1,ty_rgb,'Original') ## 讲BGR格式转为HSV ty_hsv = cv2.cvtColor(ty_img, cv2.COLOR_BGR2HSV) ## 取红色 sensitivity = 10 lower_red0 = np.array([0,100,100]) upper_red0 = np.array([sensitivity,255,255]) lower_red1 = np.array([180-sensitivity,100,100]) upper_red1 = np.array([180,255,255]) ## 设置阈值 mask_0 = cv2.inRange(ty_hsv,lower_red0,upper_red0) mask_1 = cv2.inRange(ty_hsv,lower_red1,upper_red1) mask_red = cv2.bitwise_or(mask_0, mask_1) ## 对原图像处理 res = cv2.bitwise_and(ty_img,ty_img,mask=mask_red) ## 显示取红色后的效果 res_rgb = cv2.cvtColor(res, cv2.COLOR_BGR2RGB) show_im(2,res_rgb,'Conversion') plt.savefig('ty_exred.jpg') plt.show()2.图像算术运算 (1)图像加法 1° cv2.add()
import cv2 import numpy as np x = np.uint8([250]) y = np.uint8([14]) print(cv2.add(x,y)) ## 相加,opencv超过255的截取为255 250+14 = 264 => 255 ## Out[1]: array([[255]], dtype=uint8) print(x+y) ## 相加,np超过255的会取模运算 (uint8只能表示0-255,所以取模) 250+14 = 264 % 256 = 8 ## Out[2]: array([8], dtype=uint8)
add(src1, src2, dst=None, mask=None, dtype=None)
参数说明:
- src1, src2:需要相加的两副大小和通道数相等的图像或一副图像和一个标量。
- 两幅图像相加:相加的两个图片,应该有相同的大小和通道。处理时将两副图像相同位置的像素的灰度值(灰度图像)或彩色像素各通道值(彩色图像)分别相加。
- 一副图像和一个标量(标量即单一的数值)相加:将图像所有像素的各通道值分别与标量进行相加。
- dst:可选参数,输出结果保存的变量。
- mask:图像掩膜,可选参数,为8位单通道的灰度图像,用于指定要更改的输出图像数组的元素,即输出图像像素只有mask对应位置元素不为0的部分才输出,否则该位置像素的所有通道分量都设置为0(黑色)。
- dtype:可选参数,输出图像数组的深度,即图像单个像素值的位数(如RGB用三个字节表示,则为24位,2^3*3)。
import cv2 img1 = cv2.imread("ty.jpg") x,y = img1.shape[0:2] img2 = cv2.imread("sugar.jpg") ## 查看两幅图大小和通道数是否一致,若不一致,则使用resize修改 print(img1.shape) ##Out[1]: (854, 740, 3) print(img2.shape) ##Out[2]: (543, 500, 3) img3 = cv2.resize(img2,(y,x)) print(img3.shape) ##Out[3]: (854, 740, 3) ## 将两幅图相加 img = cv2.add(img1,img3) cv2.imshow('ty', img) cv2.waitKey(0) cv2.destroyAllWindows()2° cv2.addWeighted()
addWeighted()函数是将两张相同大小,相同类型的图片(叠加)线性融合的函数,实现图像混合加权
dst = src1 * alpha + src2 * beta + gamma;。
cv2.addWeighted(InputArray src1, double alpha, InputArray src2, double beta, double gamma, OutputArray dst, int dtype=-1)
- src1:需要加权的第一个数组
- alpha:第一个数组的权重
- src2:第二数组(与第一个数组需要拥有同一个尺寸和通道数)
- beta:第二个数组的权重值,值为1-alpha
- gamma:一个加到权重总和上的标量值,可以理解为加权和后的图像的偏移量
- dst:输出的数组
- dtype:可选,输出阵列的深度,有默认值-1。
import cv2 def add_W(img1_path,img2_path,alpha=0.6,beta=0.4,gamma=0): img_1 = cv2.imread(img1_path) x,y = img_ty.shape[0:2] img_2 = cv2.imread(img2_path) img_3 = cv2.resize(img_2,(y,x)) img_aw = cv2.addWeighted(img_1,alpha,img_3,beta,gamma) cv2.imshow('ty', img_aw) cv2.waitKey(0) cv2.destroyAllWindows() add_W("ty.jpg","sugar.jpg",0.8,0.2)3° 滑动条
- cv2.createTrackbar(“滑动条的名字”, “滑动条被放置的窗口的名字”, 滑动条的默认值, 滑动条的最大值, 回调函数):绑定滑动条和窗口,定义滚动条的数值。
- cv2.getTrackbarPos(“滑动条名字”,“所在窗口”):返回滑动条的数值。
- cv2.setTrackbarPos(“滑动条名字”,“所在窗口”, 滑动条默认值)
注:滑动条返回的值为整数。
import cv2 import numpy as np ## 创建窗口 cv2.namedWindow("ty") ## 图片读取,保持两张图片数组大小一致 img_ty = cv2.imread("ty.jpg") x,y = img_ty.shape[0:2] img_candy = cv2.imread("sugar.jpg") img_candy = cv2.resize(img_candy,(y,x)) ## 用来存放两张图片加权后的结果 img = np.zeros((x,y,3),np.uint8) alpha = 0.5 ## 定义回滚函数 def callback(x): global img_ty,img_candy,img,alpha alpha = cv2.getTrackbarPos("alpha","ty") alpha = alpha * 0.01 beta = 1-alpha img = cv2.addWeighted(img_ty,alpha,img_candy,beta,0) cv2.createTrackbar("alpha","ty",0,100,callback) cv2.setTrackbarPos("alpha", "ty", 80) while(True): if cv2.waitKey(1) == ord('q'): ## waitKey的值不能为0 break cv2.imshow("ty",img) cv2.destroyAllWindows()(2)图像位运算 1° 二值化
阈值分割其实就是图像分离,对于阈值内的你想如何 *** 作,一个最简单的例子就是二值图像。
① cv2.threshold()threshold:固定阈值二值化。
ret, dst = cv2.threshold(src, thresh, maxval, type)
参数解释:
- src:输入图,只能输入单通道图像,通常来说为灰度图
- thresh:阈值
- maxval:阈值最大值,当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值
- type:二值化 *** 作的类型
- ret:方法是否执行成功
- dst:目标图像
adaptiveThreshold:自适应阈值二值化。自适应阈值二值化函数根据图片一小块区域的值来计算对应区域的阈值,从而得到也许更为合适的图片。
dst = cv2.adaptiveThreshold(src, maxval, adaptiveMethod, type, Block Size, C)
参数解释:
- src:输入图,只能输入单通道图像,通常来说为灰度图
- maxval:阈值最大值,当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值
- adaptiveMethod: 自适应方法,平均或高斯
- type:二值化 *** 作的类型
- Block Size: 图片中分块的大小,值要为奇数
- C :偏移值调整量,计算adaptiveMethod用到的参数
当且仅当两个像素都大于零时,按位AND才为真。将数字转换成二进制形式–>对同一位上的数字进行and运算(1&1=1,1&0=0,0&0=0)–>将and *** 作后的二进制转换回十进制并输出。
255的二进制码为11111111,任何数字与之与运算都为他本身。
0的二进制码为00000000,任何数字与之与运算都为0。
bitwise_and(src1, src2, dst=None, mask=None)
参数解释:
- src1、src2:为输入图像或标量,标量可以为单个数值或一个四元组。
- dst:可选输出变量,如果需要使用非None则要先定义,且其大小与输入变量相同。
- mask:图像掩膜,可选参数,为8位单通道的灰度图像,输出图像像素只有mask对应位置元素不为0的部分才输出,否则该位置像素的所有通道分量都设置为0。
mask默认为区域不为0,即不为黑色。
import cv2 import numpy as np import matplotlib.pyplot as plt img = cv2.imread('ty.jpg') ImgMask = np.zeros(img.shape,dtype=np.uint8) ImgMask[10:200,300:450] = 255 img_mask = cv2.bitwise_and(img,ImgMask) ## 默认不为0的区域输出 cv2.imshow('ty', img_mask) cv2.waitKey(0) cv2.destroyAllWindows()② mask参数
定义mask为黄色。
import cv2 import numpy as np import matplotlib.pyplot as plt img = cv2.imread('ty_yell.jpg') ## 使用hsv模型提取想要的颜色,下提取黄色 img_hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV) lower_yell = np.array([20,43,43]) upper_yell = np.array([38,255,255]) mask = cv2.inRange(img_hsv,lower_yell,upper_yell) res = cv2.bitwise_and(img,img,mask=mask) cv2.imshow('ty_ori', img) cv2.imshow('ty_ext', res) cv2.waitKey(0) cv2.destroyAllWindows()3° 位或运算
如果两个像素中的任何一个大于零,则按位“或”为真。将数字转换成二进制形式–>对同一位上的数字进行or运算(1|1=1,1|0=1,0|0=0)–>将and *** 作后的二进制转换回十进制并输出。
bitwise_or(src1, src2, dst=None, mask=None)
import cv2 import numpy as np img_ty = cv2.imread('ty_black.jpg') x,y = img_ty.shape[0:2] img = cv2.resize(img_ty, (int(y / 2), int(x / 2))) ImgMask = np.zeros(img.shape,dtype=np.uint8) ImgMask[ImgMask == 0] = 255 ImgMask[5:300,80:280] = 0 img_mask = cv2.bitwise_or(img,ImgMask) cv2.imshow('img', img) cv2.imshow('mask', ImgMask) cv2.imshow('ty_mask', img_mask) cv2.waitKey(0) cv2.destroyAllWindows()4° 位异或运算
当且仅当两个像素一个大于0一个小于0时才为真。将数字转换成二进制形式–>对同一位上的数字进行^运算(1 ^ 1=0,1 ^ 0=1,0 ^ 0=0)–>将and *** 作后的二进制转换回十进制并输出。
bitwise_xor(src1, src2, dst=None, mask=None)① 画长方形
cv2.rectangle(image, start_point, end_point, color, thickness)
参数解释:
- image:要在其上绘制矩形的图像。
- start_point:矩形的起始坐标。(X,Y)
- end_point:矩形的结束坐标。(X,Y)
- color:绘制的矩形边界线颜色。(B,G,R)
- thickness:矩形边框线的粗细像素。厚度-1像素将以指定的颜色填充矩形形状。
cv2.circle(image, center_coordinates, radius, color, thickness)
参数解释:
- image:要在其上绘制圆形的图像。
- center_coordinates:圆的中心坐标。(X,Y)
- radius:圆的半径。
- color:绘制的圆边界线颜色。(B,G,R)
- thickness:圆边界线的粗细像素。厚度-1像素将以指定的颜色填充矩形形状。
import cv2 import numpy as np ## 创建两个300*300图像 rect = np.zeros((300,300),dtype = np.uint8) circle = np.zeros((300,300),dtype = np.uint8) ## 在rect图像中填充一个长方形,在circle图像中填充一个圆形 cv2.rectangle(rect,(25,25),(275,275),255,-1) cv2.circle(circle,(150,150),150,255,-1) ## 对两个图像进行位异或运算 res = cv2.bitwise_xor(rect,circle) cv2.imshow('rect', rect) cv2.imshow('circle', circle) cv2.imshow('res', res) cv2.waitKey(0) cv2.destroyAllWindows()5° 位非运算
倒置图像中的“开”和“关”像素。~(A) = -(A+1)
bitwise_not(src, dst=None, mask=None)
import cv2 import numpy as np ## 创建一个300*300图像 rect = np.zeros((300,300),dtype = np.uint8) ## 在rect图像中填充一个长方形 cv2.rectangle(rect,(25,25),(275,275),255,-1) ## 对两个图像进行位异或运算 res = cv2.bitwise_not(rect) cv2.imshow('rect', rect) cv2.imshow('res', res) cv2.waitKey(0) cv2.destroyAllWindows()
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)