因为最近公司项目需要用到opencv对图像进行处理,所以对这一块进行了学习,现在将自己学习到的东西记录下来,以便使用。
import cv2
import numpy as np
img = cv2.imread("soble.png")
cv2.imshow("soble",img)
cv2.waitKey(10000)
但是这里有个坑,如果是中文路径,你就会发现图片读取不出来,需要换个方法
#path为图片路径
img_np = np.fromfile(path, dtype = np.uint8)
imgs = cv2.imdecode(img_np, -1)
读取像素
读取图片像素时,如果图片为灰度图像则返回的为灰度值,如果是BGR图像,返回值为B,G,R的值。
import cv2
import numpy as np
img = cv2.imread("soble.png")
#如果为灰度图像则只有一个返回值,如果BGR图像返回三个值
p = img[11,11]
print(p)
正常情况下彩色图片返回的为BGR三通道的值,如果想单独获取某一个通道值则在位置后面加上通道
import cv2
import numpy as np
img = cv2.imread("soble.png")
#如果为灰度图像则只有一个返回值,如果BGR图像返回三个值,如果加上通道值则只返回当前通道的值【0,1,2】代表蓝绿红三个通道
blue = img[11,11,0]
#此时返回蓝色通道值
print(blue)
green = img[11,11,1]
#此时返回绿色通道值
print(green)
red = img[11,11,2]
#此时返回红色通道值
print(red)
修改像素值
如果为灰度图像则修改方式为:
img[11,11] = 255
如果为BGR图像则修改方式为:
img[11,11] = [255,255,255]
或者
img[11,11,0] = 255
img[11,11,1] = 255
img[11,11,2] = 255
读取像素
这个操作大致上获取像素值跟上面是完全相似的。也是分为灰度图片和BGR图片两种,返回值也是一样的。如果是灰度图片则只返回一个值,如果是BGR图片则返回三个值
import cv2
import numpy as np
img = cv2.imread("soble.png")
blue = img.item(78,125,0)
green = img.item(78,125,1)
red = img.item(78,125,2)
print(blue)
print(green)
print(red)
修改像素值
相比于不使用numpy,numpy对像素的设置更加方便。
操作方式如下:
import cv2
import numpy as np
img = cv2.imread("soble.png")
#灰度图像:接收两个参数,第一个参数为像素位置,第二个位置为像素值
img.itemset((88,99),255)
#BGR图像 也是接收两个参数,第一个参数为像素位置,但是多了一个通道,第二个为像素值
img.itemset((88,99,0),255)
img.itemset((88,99,0),255)
img.itemset((88,99,0),255)
opencv获取图像的属性包含三个方面
1.形状
shape可以获取图像的形状
返回包含行数,列数,通道数的元组。如果是灰度图像则返回行数和列数,如果是BGR图像则返回行数、列数、通道数
import cv2
import numpy as np
#读取图像
img = cv2.imread("soble.png")
#将图像转为灰度图像
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
print(img.shape) #输出值为(428, 605, 3)
print(gray.shape) #输出值为(428, 605)
2.像素数目
size可以获取图像的像素数目
如果是灰度图像返回行数*列数,如果是BGR图像则返回行数*列数*通道数目
import cv2
import numpy as np
img = cv2.imread("soble.png")
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
print(img.size) #输出值为776820
print(gray.size) #输出值258940
可以看出将图片转为灰色图像后,图片只剩下一个通道,相比于BGR图片像素减少了很多
3.图像类型
dtype返回的是图像的数据类型
import cv2
import numpy as np
img = cv2.imread("soble.png")
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
print(img.dtype) #uint8
print(gray.dtype) #uint8
ROI(region of interest),感兴趣区域
从被处理的图像以方框、圆、椭圆、不规则多边形等方式勾勒出需要处理的区域。
可以通过各种算子(operator)和函数来求得感兴趣区域ROI,并进行图像的下一步处理。
import cv2
import numpy as np
img = cv2.imread("soble.png")
cv2.imshow('ori',img)
temp = img[100:300,100:300]
img[100:300,400:600] = temp
cv2.imshow('temp',img)
cv2.waitKey()
cv2.destroyAllWindows()
1.拆分通道
import cv2
import numpy as np
img = cv2.imread("soble.png")
cv2.imshow('ori',img)
b = img[:,:,0]
g = img[:,:,1]
r = img[:,:,2]
cv2.imshow('b',b)
cv2.imshow('g',g)
cv2.imshow('r',r)
cv2.waitKey()
cv2.destroyAllWindows()
也可以采用opencv提供的工具类进行通道拆分
import cv2
import numpy as np
img = cv2.imread("soble.png")
cv2.imshow('ori',img)
b,g,r = cv2.split(img)
cv2.imshow('b',b)
cv2.imshow('g',g)
cv2.imshow('r',r)
cv2.waitKey()
cv2.destroyAllWindows()
两种拆分方式结果相同,展示如下:
2.合并通道
通过opencv提供的工具类进行操作
import cv2
import numpy as np
img = cv2.imread("soble.png")
cv2.imshow('ori',img)
b,g,r = cv2.split(img)
result = cv2.merge([b,g,r])
cv2.imshow('result',result)
cv2.waitKey()
cv2.destroyAllWindows()
可以看到合并后和拆分之前的图像一致。
1.图像加法
Numpy加法
numpy加法采用取模加法,如果两个像素相加,当像素值小于255时则取当前相加的像素值,如果相加的像素值大于255的话则拿当前像素值对255取模
OpenCV加法
OpenCV加法采用饱和运算加法,运算方式: 结果 = cv2.add(图像1,图像2)
采用饱和运算相加时,如果相加像素值低于255则取当前相加像素值,如果相加像素值大于255则取255作为当前像素值。
需要注意的问题(参与运算的图像大小、类型必须一致)
下面代码来操作一下:
import cv2
import numpy as np
img = cv2.imread("soble.png")
img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cv2.imshow('ori',img)
a = img + img
b = cv2.add(img,img)
cv2.imshow('a',a)
cv2.imshow('b',b)
cv2.waitKey()
cv2.destroyAllWindows()
可以看出来这个图像直接相加存在很大问题,相加以后图片跟原来的图片差别很大。所以接下来要介绍的是比较常用的图像融合。相比于这个简单的图像相加效果会更好。
2.图像融合
结果图像 = 图像1*系数1 + 图像2* 系数2 + 亮度调节量
img = img1*0.3 + img2*0.7 +18
图像融合函数 addWeighted
dst = cv.addWeighted(src1,alpha,src2,beta,gamma)
dst = src1*alpha + src2*beta + gamma;
需要注意的是参数gamma不能省略
import cv2
import numpy as np
img = cv2.imread("soble.png")
img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cv2.imshow('ori',img)
result = cv2.addWeighted(img,0.3,img,0.7,0)
cv2.imshow('result',result)
cv2.waitKey()
cv2.destroyAllWindows()
经过试验发现,可以发现alpha和beta就是控制图片的显示占比,哪张图片的系数大,那么哪张图片就比较明显。
将图像由一种类型转换为另外一种类型
OpenCV提供了200多种图片转换方式,有需要的参考官方文档即可
举个简单的例子,就拿BGR转gray来说:
import cv2
import numpy as np
img = cv2.imread("soble.png")
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cv2.imshow('gray',gray)
cv2.waitKey()
cv2.destroyAllWindows()
1.图像缩放
dst = cv2.resize(src,dsize)
disze 缩放大小
b = cv2.resize(a,(122,122))
dst = cv2.resize(src,dsize,fx,fy)
fx,fy缩放大小,如果dsize不为空则按照dsize进行缩放,如果为空则按照fx,fy进行缩放
b = cv2.resize(a,None,fx=0.5,fy=0.7)
代码示例:
import cv2
import numpy as np
img = cv2.imread("soble.png")
rows,cols = img.shape[:2]
b=cv2.resize(img,(round(cols*0.5),round(rows*1.2)))
cv2.imshow('ori',img)
cv2.imshow('resize',b)
cv2.waitKey()
cv2.destroyAllWindows()
import cv2
import numpy as np
img = cv2.imread("soble.png")
rows,cols = img.shape[:2]
b=cv2.resize(img,None,fx=1,fy=0.5)
cv2.imshow('ori',img)
cv2.imshow('resize',b)
cv2.waitKey()
cv2.destroyAllWindows()
2.图像翻转
dst = cv2.flip(src,flipCode)
flipCode = 0 以X为对称轴进行翻转
flipCode > 0 以y轴为对称轴进行翻转
flipCode < 0 以y轴为对称轴进行翻转,再以x轴为对称轴进行翻转
代码示例:
import cv2
import numpy as np
img = cv2.imread("soble.png")
b= cv2.flip(img,0)
c= cv2.flip(img,1)
d= cv2.flip(img,-1)
cv2.imshow('ori',img)
cv2.imshow('b',b)
cv2.imshow('c',c)
cv2.imshow('d',d)
cv2.waitKey()
cv2.destroyAllWindows()
由于时间原因,今天先写到这里剩余部分有时间会接着写。