准备
1.安装openCV库
2.openCV python文档,清华源的cv库最新版本是4.5.5
3.GitHub地址
图片常识
openCV 中的默认颜色格式通常称为 RGB,但实际上是 BGR(字节反转)。因此,标准(24 位)彩色图像中的第一个字节将是 8 位蓝色分量,第二个字节将是绿色,第三个字节将是红色。然后第四、第五和第六个字节将是第二个像素(蓝色,然后是绿色,然后是红色),依此类推。
RGB图在cv中的顺序是BGR,(0,0,0)表示黑色,(255,255,255)表示白色
灰度图中0表示纯黑色,255表示纯白
openCV中的灰度图(GRAY)以uint8存储,RGB3通道彩色图也是uint8,范围就是0~255
BGR->GRAY转换
基本函数
1.显示和编辑图像
import cv2 as cv import sys img = cv.imread("a.jpg") if img is None: sys.exit("Could not read the image.") eye = img[52:66,70:84]#取出图片中人物的眼睛 img[20:34,48:62] = eye cv.imshow("Display window", img) k = cv.waitKey(0)#无限制地等待用户按键 if k == ord("s"): cv.imwrite("a.png", img)#图像另存为View Code
a.jpg a.png
2.拆分和合并颜色通道
import cv2 as cv import sys img = cv.imread("a.jpg") if img is None: sys.exit("Could not read the image.") b,g,r = cv.split (img)#拆分蓝 绿 红颜色通道 img = cv.merge ((b,g,r)) print(img.shape) cv.imshow("Display window", img) img[:,:,2] = 0#红色像素设置为0 cv.imshow("Display window", img) k = cv.waitKey(0)#无限制地等待用户按键View Code
3.添加边框并使用matplot展示多张图片
import cv2 as cv import numpy as np from matplotlib import pyplot as plt BLUE = [255,0,0] img1 = cv.imread('a.jpg') b,g,r = cv.split(img1) img1 = cv.merge((r,g,b)) replicate = cv.copyMakeBorder(img1,10,10,10,10,cv.BORDER_REPLICATE) reflect = cv.copyMakeBorder(img1,10,10,10,10,cv.BORDER_REFLECT) reflect101 = cv.copyMakeBorder(img1,10,10,10,10,cv.BORDER_REFLECT_101) wrap = cv.copyMakeBorder(img1,10,10,10,10,cv.BORDER_WRAP) constant= cv.copyMakeBorder(img1,10,10,10,10,cv.BORDER_CONSTANT,value=BLUE) plt.subplot(231),plt.imshow(img1),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(reflect101,'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') #图片是用matplotlib展示的,plt和cv的红蓝通道被交换了 plt.show()View Code
Figure_1.png
subplot介绍
4.与或操作与掩码的应用
例子所展示的场景:将一张白底的logo图片的logo抠出放置到另一张图片上
import cv2 as cv import numpy as np img1 = cv.imread('b.jpg') img2 = cv.imread('opencv-logo-white.png') # I want to put logo on top-left corner, So I create a ROI rows,cols,channels = img2.shape roi = img1[0:rows, 0:cols] # Now create a mask of logo and create its inverse mask also img2gray = cv.cvtColor(img2,cv.COLOR_BGR2GRAY) ret, mask = cv.threshold(img2gray, 10, 255, cv.THRESH_BINARY) #ret 为预设的thresh阈值 mask_inv = cv.bitwise_not(mask) # Now black-out the area of logo in ROI img1_bg = cv.bitwise_and(roi,roi,mask = mask_inv)#mask参数 对应点值不为0则相与,为0则相应点各通道置0 呈黑色 cv.imshow('img1bg',img1_bg) cv.waitKey(0) # Take only region of logo from logo image. img2_fg = cv.bitwise_and(img2,img2,mask = mask) cv.imshow('img2fg',img2_fg) cv.waitKey(0) # Put logo in ROI and modify the main image dst = cv.add(img1_bg,img2_fg) img1[0:rows, 0:cols ] = dst cv.imshow('res',img1) cv.waitKey(0) cv.destroyAllWindows()View Code
思路介绍:
1.先将3通道图转为灰度图
img2gray = cv.cvtColor(img2,cv.COLOR_BGR2GRAY)
灰度图的纯白区域灰度值为255,纯黑为0
logo图片(无像素以栅格显式) logo图片(无像素以白色显式) 灰度图(无像素以纯黑色显式)
2.用阈值函数得到掩码
ret, mask = cv.threshold(img2gray, 10, 255, cv.THRESH_BINARY)
threshold函数
THRESH_BINARY 指的是灰度值大于thresh(这里是10)时,输出的对应点灰度值为maxval(这里是255)
故mask描述的是原灰度图中thresh>10的区域(logo本体与英文字),在mask中该区域值均为255,其他地方均是0
mask_inv = cv.bitwise_not(mask)#得到反转掩码
3.根据反转掩码将ROI的logo区域置0,得到背景
img1_bg = cv.bitwise_and(roi,roi,mask = mask_inv)#mask参数 为0则相应点各通道置0 呈黑色,mask对应点值不为0则相与
bitwise_and函数
4.根据掩码将logo区域外的地方置0,得到前景
img2_fg = cv.bitwise_and(img2,img2,mask = mask)
5.前景与背景相加,并置于ROI的位置
dst = cv.add(img1_bg,img2_fg)
img1[0:rows, 0:cols ] = dst