OpenCV(一)之图像基本操作

什么是openCV?

OpenCV的全称是:Open Source Computer Vision Library。

OpenCV是一个基于(开源)发行的跨平台计算机视觉库,可以运行在Linux、Windows和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。


Basic Operation系列

从openCV库的最基本操作开始,主要包括图片读取、图片显示、图片输出、视频读取、图灰值化、图像截取、通道提取、通道整合、边界填充、图像加值、图像融合等等基本的操作。

Basic Operation-导入工具包

#导入所需的工具包
import cv2
import matplotlib.pyplot as plt

Basic Operation-读取图片

function:
def imread(filename, flags=None):
	从文件加载图像。
	函数imread从指定文件加载图像并返回它。如果无法读取图像(由于文件丢失,权限不正确,格式不受支持或无效),
	该函数返回一个空矩阵(Mat :: data == NULL)。
	
	目前,支持以下文件格式:
	Windows位图 - * .bmp,* .dib(始终支持)
	JPEG文件 - * .jpeg,* .jpg,*。jpe(参见注释部分)
	JPEG 2000文件 - * .jp2(参见注释部分)
	便携式网络图形 - * .png(参见“ 注释”部分)
	WebP - * .webp(参见Notes部分)
	便携式图像格式 - * .pbm,* .pgm,* .ppm * .pxm,* .pnm(始终支持)
	太阳栅格 - * .sr,* .ras(始终支持)
	TIFF文件 - * .tiff,* .tif(参见注释部分)
	OpenEXR图像文件 - * .exr(参见注释部分)
	Radiance HDR - * .hdr,* .pic(始终支持)
	Gdal支持的栅格和矢量地理空间数据(请参阅“ 注释”部分)

	参数
	filename	要加载的文件的名称。
	flags	可以采用cv :: ImreadModes值的标志

Eg.

#读取猫咪的图片
img = cv2.imread("cat.jpg")
#尝试输出
print(img)

Return.
The function imread loads an image from the specified file and returns it.
If the image cannot be read (because of missing file, improper permissions, unsupported or invalid format), the function returns an empty matrix ( Mat::data==NULL ).

Result.

[[[142 151 160]
[146 155 164]
[151 160 170]

[[154 178 190]
[154 178 190]
[121 145 157]

[183 198 200]
[128 143 145]
[127 142 144]]]

Note.

1.The function determines the type of an image by the content, not by the file extension.
2.In the case of color images, the decoded images will have the channels stored in B G R order.
3.imread()函数中ImreadModes参数有哪些作用?
ImreadModes


Basic Operation-显示图片

function:
def imshow(filename, image):
	在指定的窗口中显示图像。
	函数imshow在指定的窗口中显示图像。
	如果窗口是使用cv :: WINDOW_AUTOSIZE标志创建的,则图像将以原始大小显示,但仍然受到屏幕分辨率的限制。
	否则,缩放图像以适合窗口。
	该功能可能会缩放图像,具体取决于其深度:
	如果图像是8位无符号,则按原样显示。
	如果图像是16位无符号或32位整数,则像素除以256.即,值范围[0,255 * 256]被映射到[0,255]。
	如果图像是32位浮点,则像素值乘以255.即,值范围[0,1]映射到[0,255]。
	如果窗口是使用OpenGL支持创建的,cv :: imshow也支持ogl :: Buffer,ogl :: Texture2D和cuda :: GpuMat作为输入。
	如果在此函数之前未创建窗口,则假定使用cv :: WINDOW_AUTOSIZE创建窗口。
	如果需要显示大于屏幕分辨率的图像,则需要在imshow之前调用namedWindow(“”,WINDOW_NORMAL)。

Eg.

#显示图片函数imshow(名称,图片)
cv2.imshow('image',img)
#等待时间
cv2.waitKey(1000)
#自动关闭窗口
cv2.destroyAllWindows()

Result.
cat.jpg

Note.

1.此函数后面应跟有waitKey函数,该函数显示指定毫秒的图像,否则,它将不显示图像。
例如,waitKey(0)将无限显示窗口,直到任何按键(适用于图像显示)。
waitKey(25)将显示一个25毫秒的帧,之后显示将自动关闭。(如果你把它放在一个循环中来阅读视频,它将逐帧显示视频)
2.可以创建多个不同的窗口,但必须赋予不一样的filename
3.可以用destroyAllWindows()函数关闭所有窗口


Basic Operation-输出图片

function:
def imwrite(filename, img, params=None):
	将图像保存到指定的文件。
	函数imwrite将图像保存到指定的文件。
	基于文件扩展名选择图像格式(有关扩展名列表,请参阅cv :: imread)。
	使用此功能时,只能保存8位(或PNG,JPEG 2000和TIFF情况下的16位无符号(CV_16U))单通道,
	或者3通道(带'BGR'通道顺序)图像。
	如果格式,深度或通道顺序不同,请使用Mat :: convertTo和cv :: cvtColor在保存之前进行转换。
	或者,使用通用FileStorage I / O函数将图像保存为XML或YAML格式。
	使用此功能可以使用Alpha通道存储PNG图像。为此,创建8位(或16位)4通道图像BGRA,其中alpha通道最后。
	完全透明的像素应将alpha设置为0,完全不透明的像素应将alpha设置为255/65535。

	参数
	filename 文件名。
	IMG	要保存的图像。
	PARAMS	编码为对的格式特定参数(paramId_1,paramValue_1,paramId_2,paramValue_2,...)

Eg.

#保存输出结果,imwrite(图片名称,图片)
cv2.imwrite('mycat.png',img1)

Note.
ImwriteFlags


Basic Operation-读取视频

function:
def VideoCapture(source):
	@param source video.

Eg.

#读取视频
vc = cv2.VideoCapture('test.mp4')
#检查是否打开摄像头
if vc.isOpened():
    open, frame = vc.read()
else:
    open=False
#用一个while循环对视频进行抽帧处理
while open:
    ret,frame = vc.read()
    if frame is None:
        break
    if ret == True:
        gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) #这里使用cv2的BGR2GRAY把图像转为灰色
        cv2.imshow('result',gray)
        if cv2.waitKey(10) & 0xFF==27: #记录按键ESC退出键的ASCII码为27
            break
#释放视频
vc.release()
cv2.destroyAllWindows()

Note.
1.将视频读入后,逐帧处理,就将其分治为一张图像的问题,假如说一张图像的维度为(px,px,channel)现在可以认为是(px,px,channel,time)


Basic Operation-图灰值化

Eg.

#在读取图片时,将其flags赋为IMREAD_GRAYSCALE
img = cv2.imread('cat.jpg',cv2.IMREAD_GRAYSCALE)

Result.

[[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]]

Note.
1.图片灰值化之后读取的matrix是一个二维matrix,在源码中查看IMREAD_GRAYSCALE的值为0


Basic Operation-图像截取

Eg.

#截取部分图像数据 img[像素段,像素段]
cat = cv2.cvtColor(img[0:100,0:100],cv2.COLOR_BGR2RGB)
plt.imshow(cat)
plt.show()

Result.
截取
Note.
1.可以直接在matrix中,定义下标区间,截取图像


Basic Operation-通道提取

function:
def split(m, mv=None):
	@param m input multi-channel array.
    @param mv output vector of arrays; the arrays themselves are reallocated, if needed.

Eg.

#颜色通道提取
b,g,r = cv2.split(img)
plt.subplot(131)
plt.imshow(b)
plt.title("B channel")

plt.subplot(132)
plt.imshow(g)
plt.title("G channel")

plt.subplot(133)
plt.imshow(r)
plt.title("R channel")

plt.show()

Note.
1.通过split()函数可以读取图像的BGR channel ,需要注意的地方是,一般情况下其他图像处理库都是RGB或许需要进行转换


Basic Operation-通道整合

function:
def merge(mv, dst=None): 
	@param mv input vector of matrices to be merged; all the matrices in mv must have the same
    size and the same depth.
    @param dst output array of the same size and the same depth as mv[0]; The number of channels will
    be the total number of channels in the matrix array.

Eg.

#整合BGR通道
img = cv2.merge((b,g,r))
print(img.shape)

#观察三个Channel各自的表现情况
#BGR 保留R
cur_img = img.copy()
cur_img[:,:,0]=0 #B=0
cur_img[:,:,1]=0 #G=0
cv2.imshow('cat',cur_img)
cv2.waitKey(1000)

#BGR 保留G
cur_img = img.copy()
cur_img[:,:,0]=0 #B=0
cur_img[:,:,2]=0 #R=0
cv2.imshow('cat',cur_img)
cv2.waitKey(1000)

#BGR 保留B
cur_img = img.copy()
cur_img[:,:,1]=0 #G=0
cur_img[:,:,2]=0 #R=0
cv2.imshow('cat',cur_img)
cv2.waitKey(1000)

Result.
BGR
Note.
1.需要一样的Size和depth


Basic Operation-边界填充

function:
def copyMakeBorder(src,top, bottom, left, right ,borderType,value):
	@param src Source image
    @param top The depth at which the image expands to the top
    @param bottom The depth at which the image expands to the bottom
    @param left The depth at which the image expands to the left
    @param right The depth at which the image expands to the right
    @param borderType Type of boundary
    @param value Specify a constant when the boundary fill type is constant

Eg.

#边界填充
top,bottom,left,right = (50,50,50,50)
borderType1 = cv2.BORDER_REPLICATE
borderType2 = cv2.BORDER_REFLECT
borderType3 = cv2.BORDER_REFLECT_101
borderType4 = cv2.BORDER_WRAP
borderType5 = cv2.BORDER_CONSTANT
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
#填充的方式
replicate = cv2.copyMakeBorder(img,top,bottom,left,right,borderType=borderType1)
reflect = cv2.copyMakeBorder(img,top,bottom,left,right,borderType=borderType2)
reflect_101 = cv2.copyMakeBorder(img,top,bottom,left,right,borderType=borderType3)
wrap = cv2.copyMakeBorder(img,top,bottom,left,right,borderType=borderType4)
constant = cv2.copyMakeBorder(img,top,bottom,left,right,borderType=borderType5,value=1)

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(reflect_101,'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()

Result.
compare
Note.
填充类型有如下几种:
1.cv2.BORDER_REPLICATE 直接使用边界的颜色填充 aaaaaaa | abcdefg | ggggggg
2.cv2.BORDER_REFLECT 类型镜子的反射一样,以边界为线进行倒映 gfedcba | abcdefg | gfedcba
3.cv2.BORDER_REFLECT_101 与reflect方法类似,不过边界点去掉其一 gfedcb | abcdefg | fedcba
4.cv2.BORDER_WRAP 外包装法,按照图片进行循环填充 abcdefg | abcdefg | abcdefg
5.cv2.BORDER_CONSTANT 常量填充 0000000 | abcdefg | 0000000


Basic Operation-图像加值

Eg.

#matrix数值的计算
img_cat = cv2.imread('cat.jpg')
img_dog = cv2.imread('dog.jpg')

#相当于每个元素都加上某个数值
img_cat2 = img_cat + 10

print("cat.jpg的matrix输出为(只输出Bchannel的前5行):")
print(img_cat[0:5,:,0])
print("加10之后cat.jpg的matrix输出为(只输出Bchannel的前5行):")
print(img_cat2[0:5,:,0])

#两个图片相加需要一样的维度和,两个matrix相加对应的元素相加后,取余255得到值,并填入
img = img_cat+img_cat2

print("前后两个matrix相加的输出为:")
print(img[0:5,:,0])

#使用cv2中自带的add函数,每个元素对应相加后不会进行取余,x>=255 输出255 反之保持原值
print("使用cv2库中输出为:")
print(cv2.add(img_cat,img_cat2)[0:5,:,0])

Result.

cat.jpg的matrix输出为(只输出Bchannel的前5行):
[[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]]
加10之后cat.jpg的matrix输出为(只输出Bchannel的前5行):
[[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]]
前后两个matrix相加的输出为:
[[ 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]]
使用cv2库中输出为:
[[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]]

Note.
1.使用得到的matrix矩阵加上一个常量,为matrix中每一个元素加上常量然后输出
2.matrix的相加应该有一样的维度
3.单通道图层相加后,数值大于255,会做取余255的操作
4.用自带的add()函数相加,结果大于等于255则输出255,,反之输出原值


Basic Operation-图像融合

function:
def resize(src, dsize, dst=None, fx=None, fy=None, interpolation=None):
	调整图像大小。
	函数resize将图像src的大小调整为或者达到指定的大小。
	请注意,如果不考虑初始dst类型或大小,可以调用以下方法:
//明确指定dsize = dst.size(); fx和fy将从中计算出来。
resize(src,dst,dst.size(),0,0,interpolation);
	相反,大小和类型从派生src,dsize,fx,和fy,如果要调整src的大小以使其适合预先创建的dst,可以按如下方式调用该函数:
//指定fx和fy并让函数计算目标图像大小。
调整大小(src,dst,Size(),0.5,0.5,插值);
def addWeighted(src1, alpha, src2, beta, gamma, dst=None, dtype=None):
	计算两个数组的加权和。

Eg.

#对cat图片进行缩放
img1 = cv2.resize(img_cat,(400,400),fx=2,fy=2)
img2 = cv2.resize(img_cat,(0,0),fx=1,fy=3)
img3 = cv2.resize(img_cat,(0,0),fx=3,fy=3)

#创建一个新的图像集,对比更明显
plt.subplot(141)
plt.imshow(img_cat)
plt.subplot(142)
plt.imshow(img1)
plt.subplot(143)
plt.imshow(img2)
plt.subplot(144)
plt.imshow(img3)

#将dog图片的像素改为与cat图像一致
img_dog = cv2.resize(img_dog,(500,414))
plt.imshow(cv2.addWeighted(img_cat,0.3,img_dog,0.3,0))
plt.show()

Result.
ronghe
Note.
1.在rize()中的参数类型有以下需要注意的地方:
@param dst 目标图像,当@param dsize不为0的时候,dst目标图像的size则为dsize所定义的大小

2.dsize和(Fx,Fy)二者不可都为零,当dsize为0的时候,相对应的dst目标图像的size计算方法如下所示:
d s i z e = S i z e ( R o u n d ( F x ∗ S r c . c o l s ) , R o u n d ( F y ∗ S r c . r o w s ) ) dsize = Size(Round(Fx*Src.cols),Round(Fy*Src.rows)) dsize=Size(Round(FxSrc.cols),Round(FySrc.rows))

3.Fx是水平轴上的比例因子,当其为0时,按以下公式进行计算:
( d o u b l e ) d s i z e . w i d t h / s r c . c o l s (double)dsize.width/src.cols (double)dsize.width/src.cols

4.Fy是垂直轴上的比例因子,当其为0时,按以下公式进行计算:
( d o u b l e ) d s i z e . h e i g h t / s r c . r o w s (double)dsize.height/src.rows (double)dsize.height/src.rows

5.interpolation - 插值方法,共有5种:
1)INTER_NEAREST - 最近邻插值法
2)INTER_LINEAR - 双线性插值法(默认)
3)INTER_AREA - 基于局部像素的重采样(resampling using pixel area relation)
对于图像抽取(image decimation)来说,这可能是一个更好的方法。但如果是放大图像时,它和最近邻法的效果类似。
4)INTER_CUBIC - 基于4x4像素邻域的3次插值法
5)INTER_LANCZOS4 - 基于8x8像素邻域的Lanczos插值
要缩小图像,通常会使用#INTER_AREA插值,而放大的图像,通常会使用C#INTER_CUBIC(速度较慢)或#INTER_LINEAR(速度虽快,但效果也较为可观)。

6.addWeighted函数中的dst输出图像的像素点计算方式如下所示:
d s t = s r c 1 ∗ α + s r c 2 ∗ β + γ ; dst = src1*\alpha + src2*\beta + \gamma; dst=src1α+src2β+γ;

7.addWeighted函数中的dtype参数,可以输出dst的depth,当设置为-1时,dst.depth =src1.depth


补充点,及细节知识

1.在plt.imshow()函数中:
def imshow(X, cmap=None, norm=None, aspect=None, interpolation=None, alpha=None,vmin=None, vmax=None, origin=None, extent=None, shape=None,filternorm=1, filterrad=4.0, imlim=None, resample=None, url=None,hold=None, data=None, **kwargs):
函数的参数有很多,关于其中一项的cmap图谱的可选项,做补充,
cmap: 颜色图谱(colormap), 默认绘制为RGB(A)颜色空间

颜色图谱描述
autumn红-橙-黄
bone黑-白,x线
cool青-洋红
copper黑-铜
flag红-白-蓝-黑
gray黑-白
hot黑-红-黄-白
hsvhsv颜色空间, 红-黄-绿-青-蓝-洋红-红
inferno黑-红-黄
jet蓝-青-黄-红
magma黑-红-白
pink黑-粉-白
plasma绿-红-黄
prism红-黄-绿-蓝-紫-…-绿模式
spring洋红-黄
summer绿-黄
viridis蓝-绿-黄
winter蓝-绿

2.在cv2中,不止读取图像颜色通道不是常规的RGB顺序而是BGR,对于图像的weight和height也是反序


3.在底下会补充更多关于resize()函数中插值interpolation的思考和分析


END

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值