主要是关于矩阵(图像)变换或者矩阵内元素变换
2.1 roi截取
截图
import cv2 as cv
lena = cv.imread(r"C:\Users\LENOVO\Desktop\lena.png")
roi = lena[100:200,100:200]#截取图片中的100-200行与列的部分
lena[0:100,100:200] = roi
cv.imshow("lena",lena)
cv.waitKey(0)
效果:
2.2 添加边界:copyMakeBorder
img_boder=cv2.copyMakeBorder(img,top,bottom,left,right,borderType,value)
#img:输入图像
#top,bottom,left,right:各边界的宽度
#borderType:边界形式
cv2.BORDER_CONSTANT, 带颜色的边界,需要传入另外一个颜色值
cv2.BORDER_REFLECT, 边缘元素的镜像反射做为边界
cv2.BORDER_REFLECT_101/cv2.BORDER_DEFAULT
cv2.BORDER_REPLICATE, 边缘元素的复制做为边界
CV2.BORDER_WRAP,
#value:边界的颜色值,如:[0,255,0]代表绿色
代码:
import cv2 as cv
import matplotlib.pyplot as plt
img2 = cv.imread(r"C:\Users\LENOVO\Desktop\lena.png")
img = cv.cvtColor(img2,cv.COLOR_BGR2RGB) #matplotlib的图像为RGB格式,但cv为BGR
constant = cv.copyMakeBorder(img,20,20,20,20,cv.BORDER_CONSTANT,value=[0,255,0])
reflect = cv.copyMakeBorder(img,20,20,20,20,cv.BORDER_REFLECT)
reflect01 = cv.copyMakeBorder(img,20,20,20,20,cv.BORDER_REFLECT_101)
replicate = cv.copyMakeBorder(img,20,20,20,20,cv.BORDER_REPLICATE)
wrap = cv.copyMakeBorder(img,20,20,20,20,cv.BORDER_WRAP)
titles = ["constant","reflect","reflect01","replicate","wrap"]
images = [constant,reflect,reflect01,replicate,wrap]
for i in range(5):
plt.subplot(2,3,i+1),plt.imshow(images[i]),plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
效果:
2.3 图片相加:add或addWeighted
前提:当两张图片大小相等时,可以将对应坐标的每个RGB值分别相加。
add():普通相加
img_add = cv2.add(img1,img2,mask)
#img1,img2:进行相加操作的图片,当RGB(或灰度值)大于255时,自动取255
#mask:掩膜,主要用于遮挡某些区域
#img_add:相加结果
代码:
import cv2 as cv
import numpy as np
img1 = cv.imread(r"C:\Users\LENOVO\Desktop\lena.png",0)
roi_img = np.zeros(img1.shape[0:2],dtype=np.uint8)
#print(img1.shape[0:2])
roi_img[100:150,100:150]=255
img_add = cv.add(img1,img1)
img_add_mask = cv.add(img1,img1,mask=roi_img)
#cv.imshow("img1",img1)
#cv.imshow("roi_img",roi_img)
cv.imshow("img_add",img_add)
cv.imshow("img_add_mask",img_add_mask)
cv.waitKey(0)
效果图:
有掩膜:
无掩膜:
addWeighted():有权重相加
img_add = cv2.addWeighted(img1,a,img2,b,c)
#img1:图片1
#alpha:img1的权重
#img2:图片2
#b:img1的权重
#c:常量值,图像相加后再加上常量值
#img_add:相加结果
代码:
import cv2 as cv
lena = cv.imread(r"C:\Users\LENOVO\Desktop\lena.png",0)
rice = cv.imread(r"C:\Users\LENOVO\Desktop\Rice.png",0)
blend = cv.addWeighted(lena,0.5,rice,0.9,0)
cv.imshow("blend",blend)
cv.waitKey(0)
cv.destroyAllWindows()
结果:
2.4 图像放大缩小(插值):resize
将每两个像素点之间插入介于这两点大小之间的像素值的点
cv2.resize(src,dsize,fx,fy,interpolation)
#src: 输入图像对象
#dsize:输出矩阵/图像的大小,为0时计算方式如下:dsize = Size(round(fx*src.cols),round(fy*src.rows))
#fx: 水平轴的缩放因子,为0时计算方式: (double)dsize.width/src.cols
#fy: 垂直轴的缩放因子,为0时计算方式: (double)dsize.heigh/src.rows
#interpolation:插值算法
常用插值算法:
代码:
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread(r"C:\Users\LENOVO\Desktop\lena.png")
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
res = cv2.resize(img,None,fx=2, fy=2, interpolation = cv2.INTER_CUBIC)
plt.subplot(1,2,1),plt.imshow(img),plt.title('before')
plt.subplot(1,2,2),plt.imshow(res),plt.title('after')
plt.show()
结果:
2.5 仿射变换:warpAffine
仿射变换包括图像的平移,旋转(也可通过getRotationMatrix2D得到同样效果),放缩。其实质均是将图片乘以某个变换矩阵
平移:
点(x,y)平移到(x+tx, y+ty)
warpAffine实现平移:
dst = cv2.warpAffine(img,M,(cols,rows))
#img:平移前图像
#dst:平移后图像
#M:平移矩阵,形式为[[1,0,Mx],[0,1,My]]
#(cols,rows):平移后图像大小
代码:
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread(r"C:\Users\LENOVO\Desktop\lena.png",0)
rows,cols = img.shape[:2]
M=np.float32([[1,0,100],[0,1,50]])
dst = cv2.warpAffine(img,M,(cols,rows))
plt.subplot(1,2,1),plt.imshow(img),plt.title('before')
plt.subplot(1,2,2),plt.imshow(dst),plt.title('after')
plt.show()
结果:
旋转,放缩原理在后面,仅有变换矩阵不同,不再演示。
放缩:放大和缩小指相对于原坐标(x,y),变换为了(a*x, b*y),即水平方向放大了a倍,水平方向放大了b倍,其对应的转变矩阵如下:
旋转:将(x,y),以坐标原点为中心,顺时针方向旋转α得到(x1,y1), 有如下关系x1 = xcosα-ysinα, y1 =xsinα+ycosα; 因此可以构建对应的转变矩阵如下:
opencv将其扩展到,任意点center为中心进行顺时针旋转α,放大scale倍的,转变矩阵如下:
其中,仿射变换矩阵可由cv2.getRotationMatrix2D()获得:
img_rotated = cv2.getRotationMatrix2D(center,angle,scale)
#center:旋转的中心点坐标
#angle:旋转角度,单位为度数,证书表示逆时针旋转
#scale:同方向的放大倍数
代码:
import cv2
import numpy as np
from matplotlib import pyplot as plt
class BBox(object):
def __init__(self, bbox):
self.left = bbox[0]
self.top = bbox[1]
self.right = bbox[2]
self.bottom = bbox[3]
img = cv2.imread(r"C:\Users\LENOVO\Desktop\lena.png")
rows,cols,ch = img.shape
box = [0, 0, rows, cols]
bbox = BBox(box)
center = ((bbox.left + bbox.right) / 2, (bbox.top + bbox.bottom) / 2)
dst = cv2.getRotationMatrix2D(center,60,1)
img_rotated = cv2.warpAffine(img,dst,(rows,cols))
plt.subplot(1,2,1),plt.imshow(img),plt.title('before')
plt.subplot(1,2,2),plt.imshow(img_rotated),plt.title('after')
plt.show()
结果:
仿射变换矩阵的获得可以通过函数getAffineTransform获得,并不局限于变换方式:
cv2.getAffineTransform(src,dst) 返回2*3的转变矩阵
#src:原图像中的三组坐标,如float32([[50,50],[200,50],[50,200]])
#dst: 转换后的对应三组坐标,如float32([[10,100],[200,50],[100,250]])
代码如下:
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread(r"C:\Users\LENOVO\Desktop\lena.png")
rows,cols,ch = img.shape
pts1 = np.float32([[50,50],[200,50],[50,200]])
pts2 = np.float32([[10,100],[200,50],[100,250]])
dst = cv2.getAffineTransform(pts1,pts2)
img_rotated = cv2.warpAffine(img,dst,(rows,cols))
plt.subplot(1,2,1),plt.imshow(img),plt.title('before')
plt.subplot(1,2,2),plt.imshow(img_rotated),plt.title('after')
plt.show()
结果如下: