opencv用来做什么

对数据进行预处理和后处理。相比于PIL来说,opencv能够实现的功能更多

核心操作

opencv拿来做什么

对数据进行预处理和后处理。相比于PIL来说,opencv能够实现的功能更多

常见的图像

1.在图像中有宽,高,通道等概念。我们常见的图像格式有bmp(位图),jpg,png
bmp:是一种原始的图像格式,存储的空间非常高
图像压缩:有损和无损。一般是通过傅里叶变换,将时域转频域然后去掉一些东西得到的。
jpg:jpg是对bmp的图像进行有损压缩后得到的。
png:jpg一般是三通道(w,w,c),png一般是四通道(h,w,c,a)通道a代表透明度。

图像读取

1.读取图片

import cv2
img=cv2.imread(r"路径")#可以设置读出的格式
cv2.imshow("pic",img)#数据类型是np.ndarray
cv2.waitKey(0)#读出的是HWC

2.写图像

import numpy as np
import cv2
img=np.empty((200,200,3),np.uint8)
img[...,0]=255#...表示前面的维度都保留,取索引为0的通道
img[...,1]=0#读出来的为bgr,和一般的rgb有差别
img[...,2]=0
img=img[...,::-1]#将图像转为RGB格式,numpy数组操作
cv2.imwrite("img_save.jpg",img)

3.视频读取

import cv2
cap=cv2.VideoCapture("F:\\1.mp4")#读取摄像头,视频,或者给一个rtsp的视频流
while True:
    '''
    视频是由图片一帧一帧组合而成的
    所以用一个循环来一帧一帧读取视频图片
    ret表示是否读取成功
    frame表示读取出来的图像
    '''
    ret,frame=cap.read()
    cv2.imshow("frame",frame)
    if cv2.waitKey(10)&0xFF==ord("q"):#读取一张图片之后等待的时间和一个监听按键
        break
cap.release()
cv2.destroyAllWindows()

色彩空间与转换
HSV颜色空间
HSV格式中,H(色彩/色度),S(饱和度),V(亮度),可以用来表示一种颜色的深浅度,HSV的像素是连续的。
对比度:对亮度进行操作
在每一个像素上进行一个乘法运算即乘以a,再加上一个b

import cv2

src = cv2.imread(r"1.jpg")

# dst = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
# dst = cv2.cvtColor(src, cv2.COLOR_BGR2HSV)
# print(dst.shape)
dst2 = cv2.convertScaleAbs(src, alpha=6, beta=1)#alpha为进行放大的倍数

cv2.imshow("src show", src)
cv2.imshow("dst show", dst2)
cv2.waitKey(0)

opencv存储rgb格式为png图片 opencv支持的图片格式_卷积核


画图

图像坐标是满足笛卡尔坐标系的

import cv2
import numpy as np

img = cv2.imread(r"1.jpg")
'''
thickness设置为-1,表示图形的填充
'''
cv2.line(img, (100, 30), (210, 180), color=(0, 0, 255), thickness=2)
cv2.circle(img, (50, 50), 30, (0, 0, 255), 2)
cv2.rectangle(img, (100, 30), (210, 180), color=(0, 0, 255), thickness=2)
cv2.ellipse(img, (100, 100), (100, 50), 0, 0, 360, (255, 0, 0), -1)

pts = np.array([[10, 5], [50, 10], [70, 20], [20, 30]], np.int32)
pts = pts.reshape((-1, 1, 2))
cv2.polylines(img, [pts], True, (0, 0, 255), 2)

cv2.putText(img, 'beautiful girl', (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 1, lineType=cv2.LINE_AA)

cv2.imshow("pic show", img)
cv2.waitKey(0)

阈值操作
1.二值化(将RGB图像转为灰度图,然后进行二值化操作)

import cv2

img = cv2.imread("1.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)

cv2.imshow("gray",gray)
cv2.imshow('binary', binary)
cv2.waitKey(0)

2.自适应阈值

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('2.jpg', 0)#必须要转灰度图在进行阈值操作
# img = cv2.GaussianBlur(img, (5, 5), 0)

ret, th1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)#原始
th2 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C,
                            cv2.THRESH_BINARY, 11, 2)#平均
th3 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
                            cv2.THRESH_BINARY, 11, 2)#高斯

titles = ['Original Image', 'Global Thresholding (v = 127)',
          'Adaptive Mean Thresholding', 'Adaptive Gaussian Thresholding']
images = [img, th1, th2, th3]

for i in range(4):
    plt.subplot(2, 2, i+1), plt.imshow(images[i], 'gray')#将四图画出来
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])#消除坐标框
plt.show()

图像上的运算
计算的时候会有一个范围限制(0,255)超过会被自动设置为最大值

import cv2
import numpy as np

x = np.uint8([250])
y = np.uint8([10])

print(cv2.add(x,y))
print(cv2.subtract(y,x))

按位运算
与 或 非

import cv2
img1 = cv2.imread('1.jpg')
img2 = cv2.imread('6.jpg')
# img = cv2.add(img1,img2)
# dst = cv2.addWeighted(img1, 0.7, img2, 0.3, 0)#像素权重融合
# cv2.imshow("...",dst)
# cv2.waitKey(0)
rows, cols, channels = img1.shape
roi = img1[0:rows, 0:cols]
img2gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
ret, mask = cv2.threshold(img2gray, 10, 255, cv2.THRESH_BINARY)
# cv2.imshow("dd",mask)
# cv2.waitKey(0)
# exit()
mask_inv = cv2.bitwise_not(mask)#非操作
# cv2.imshow("dd",mask_inv)
img1_bg = cv2.bitwise_and(roi, roi, mask=mask_inv)#与操作
# cv2.imshow("img1_bg",img1_bg)
# cv2.waitKey(0)
# exit()
img2_fg = cv2.bitwise_and(img2, img2, mask=mask)#与操作
cv2.imshow("img2_fg",img2_fg)
cv2.waitKey(0)
exit()
dst = cv2.add(img1_bg, img2_fg)#加法操作
img1[0:rows, 0:cols] = dst
cv2.imshow('res', img1)
cv2.waitKey(0)

图像的几何变换

1.仿射变换(线性变换)

原理:任意一个二维图像,乘以一个仿射矩阵都能够进行图像的变换。仿射变换是在三维空间进行的,所以会对二维图像加一个维度。

opencv存储rgb格式为png图片 opencv支持的图片格式_高斯滤波_02


乘以不同的仿射矩阵,对形状有不同的变化:

平移变换:

opencv存储rgb格式为png图片 opencv支持的图片格式_opencv存储rgb格式为png图片_03


翻转变换:

opencv存储rgb格式为png图片 opencv支持的图片格式_opencv_04


倾斜变换:

opencv存储rgb格式为png图片 opencv支持的图片格式_高斯滤波_05


代码实现:

import cv2
import numpy as np
src = cv2.imread('1.jpg')
rows, cols, channel = src.shape#矩阵的第三层没有表示出来
M = np.float32([[1, 0, 50], [0, 1, 50]])#平移
M = np.float32([[0.5, 0, 0], [0, 0.5, 0]])#缩小操作
M = np.float32([[-0.5, 0, cols // 2], [0, 0.5, 0]])#翻转加缩小
M = np.float32([[1, 0.5, 0], [0, 1, 0]])#倾斜
M = cv2.getRotationMatrix2D((cols / 2, rows / 2), 45, 0.7)
dst = cv2.warpAffine(src, M, (cols, rows))
cv2.imshow('src pic', src)
cv2.imshow('dst pic', dst)
cv2.waitKey(0)

透视变换

在初始图像上寻找四个点,然后拉伸带二维平面作为输出。需要确定的就是四个角的坐标位置,和进行拉伸的四个点的位置,会根据这四个点得到一个透视矩阵,对图像进行变换

import cv2
import numpy as np

img = cv2.imread("2.jpg")

pts1 = np.float32([[25, 30], [179, 25], [12, 188], [189, 190]])
pts2 = np.float32([[0, 0], [200, 0], [0, 200], [200, 200]])

M = cv2.getPerspectiveTransform(pts1, pts2)
dst = cv2.warpPerspective(img, M, (200, 201))

cv2.imshow("src", img)
cv2.imshow("dst", dst)

cv2.waitKey(0)

膨胀操作
膨胀操作的前提是图像是一个二值图。膨胀操作膨胀的是白颜色的区域,黑颜色的区域不会进行膨胀。

前提是二值图,膨胀和腐蚀都是在白色的像素上进行的
开操作先腐蚀后膨胀,用于去噪
闭操作先膨胀在腐蚀,补漏洞
梯度膨胀减去腐蚀的,就是一个提取轮廓的操作
顶帽操作是先做开运算,然后用原图减去开运算,用途是提取原图中的噪点
黑帽操作是原图像转区闭运算,用途是获取到原图上面的噪点

import cv2 as cv

img = cv.imread("4.jpg", 0)
#后面的数字为设置膨胀尺度
kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))
# dst = cv.dilate(img, kernel)  # 膨胀
# dst = cv.erode(img, kernel) #腐蚀
# dst = cv.morphologyEx(img, cv.MORPH_OPEN, kernel) #开
# dst = cv.morphologyEx(img, cv.MORPH_CLOSE, kernel)  # 闭
# dst = cv.morphologyEx(img, cv.MORPH_GRADIENT, kernel)  # 梯度
# dst = cv.morphologyEx(img, cv.MORPH_TOPHAT, kernel) # 顶帽
dst = cv.morphologyEx(img, cv.MORPH_BLACKHAT, kernel) # 黑帽
cv.imshow('src', img)
cv.imshow('dst', dst)
cv.waitKey(0)

图像滤波

滤波的概念:

opencv存储rgb格式为png图片 opencv支持的图片格式_opencv存储rgb格式为png图片_06


对图像的分析分为时域和频域

时域分析:与空间有关的,在图像像素或者语音信号上取位置的某一个点的分析

频域分析:分析的是两个点之间的变化

滤波:滤波就是把不需要的滤波频域信号去点的操作
滤波分为低通滤波,高通滤波,中值滤波,阻带滤波
对于一张图像,背景图一般为低频信号,轮廓一般为高频信号。低通滤波就是去掉轮廓信息,留下背景信息,表现为使图像变模糊,主要用于去噪高通滤波就是用于提取轮廓
低通滤波:卷积,高斯滤波,

卷积:

opencv存储rgb格式为png图片 opencv支持的图片格式_卷积核_07


从左到有依次为像素图,卷积核,特征图。根据卷积核的特性,来保留下某一种特性的特征图。

import cv2
import numpy as np
src = cv2.imread(r"1.jpg")
#卷积
kernel = np.array([[1, 1, 0], [1, 0, -1], [0, -1, -1]], np.float32)  # 定义一个核
dst = cv2.filter2D(src, -1, kernel=kernel)
cv2.imshow("src show", src)
cv2.imshow("dst show", dst)
cv2.waitKey(0)

opencv存储rgb格式为png图片 opencv支持的图片格式_opencv_08


均值滤波:

均值滤波字面上理解就是平均值,其卷积核(3x3为例)如下:

opencv存储rgb格式为png图片 opencv支持的图片格式_opencv_09

import cv2
src = cv2.imread(r"1.jpg")
dst = cv2.blur(src,(3,3))
cv2.imshow("src show", src)
cv2.imshow("dst show", dst)
cv2.waitKey(0)

opencv存储rgb格式为png图片 opencv支持的图片格式_卷积核_10


高斯滤波:

高斯滤波一般用来去除高斯噪点

高斯噪点:分布类似于高斯分布的噪点

import cv2
import numpy as np
src = cv2.imread(r"1.jpg")
#高斯滤波
dst = cv2.GaussianBlur(src, (3, 3), 1)#方差为1的高斯滤波
cv2.imshow("src show", src)
cv2.imshow("dst show", dst)
cv2.waitKey(0)

opencv存储rgb格式为png图片 opencv支持的图片格式_中值滤波_11


中值滤波:

中值滤波将每一像素点的灰度值设置为该点某邻域窗口内的所有像素点灰度值的中值。

中值滤波一般用来处理椒盐噪点如下图所示:

import cv2
src = cv2.imread(r"5.jpg")
dst = cv2.medianBlur(src,3)
cv2.imshow("src show", src)
cv2.imshow("dst show", dst)
cv2.waitKey(0)

opencv存储rgb格式为png图片 opencv支持的图片格式_opencv_12


双边滤波:

双边滤波是一种非线性的滤波方法,是结合图像的空间邻近度和像素值相似度的一种折中处理 。(处理断断续续的线)

import cv2
src = cv2.imread(r"5.jpg")
dst = cv2.bilateralFilter(src,9,75,75)
cv2.imshow("src show", src)
cv2.imshow("dst show", dst)
cv2.waitKey(0)

opencv存储rgb格式为png图片 opencv支持的图片格式_opencv_13


效果明显没有中值滤波好,所以采用哪种滤波要根据噪声来确定。

锐化算子

laplacian算子

周围能量降低,中间能量变高,轮廓更加突出

高通滤波需要自己定义一个滤波器,其卷积核(3x3为例)如下:

opencv存储rgb格式为png图片 opencv支持的图片格式_opencv存储rgb格式为png图片_14

import cv2
import numpy as np
src = cv2.imread(r"1.jpg")
Laplace = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]], np.float32) #定义一个滤波核
dst = cv2.filter2D(src, -1, kernel=Laplace)
cv2.imshow("src show", src)
cv2.imshow("dst show", dst)
cv2.waitKey(0)

opencv存储rgb格式为png图片 opencv支持的图片格式_opencv_15


USM锐化:

先进行高斯滤波,再让原图和滤波后的图进行加权叠加

把低频信号尽量去掉

import cv2
src = cv2.imread(r"1.jpg")
dst = cv2.GaussianBlur(src,ksize=(5,5),sigmaX=0)# 先高斯,作用是模糊去噪
dst = cv2.addWeighted(src, 3, dst, -2, 0)# 后加权
cv2.imshow("src show", src)
cv2.imshow("dst show", dst)
cv2.waitKey(0)

opencv存储rgb格式为png图片 opencv支持的图片格式_opencv_16

梯度算子

梯度算子分为:sobel,scharr,laplacian梯度滤波器
Sobel,Scharr 其实就是求一阶或二阶导数。
Scharr 是对 Sobel(使用小的卷积核求解求解梯度角度时)的优化。
Laplacian 是求二阶导数。

sobel算子

sobel算子是高斯平滑和微分操作的结合体,所以它的抗噪声能力很强

梯度算子有两个方向,即X和Y方向,X和Y方向都有各自的作用,既对图像进行了去噪,也完成了主要特征的提取

X方向上:

opencv存储rgb格式为png图片 opencv支持的图片格式_opencv存储rgb格式为png图片_17


从横向上来看求得是相邻像素的插值,即高通滤波

从纵向上来看类似于变形的高斯滤波,即低通滤波

Y方向上:

opencv存储rgb格式为png图片 opencv支持的图片格式_opencv存储rgb格式为png图片_18


从纵向上来看求得是相邻像素的插值,即高通滤波

从横向上来看类似于变形的高斯滤波,即低通滤波

计算梯度幅值和方向:

opencv存储rgb格式为png图片 opencv支持的图片格式_中值滤波_19


实现代码和效果:

import cv2
src = cv2.imread(r"2.jpg")
dst1 = cv2.Sobel(src,-1,1,0)# 只计算x方向的梯度
dst2 = cv2.Sobel(src,-1,0,1)# 只计算y方向的梯度
dst = cv2.add(dst2,dst1)
cv2.imshow("src show", src)
cv2.imshow("dst2 show", dst2)
cv2.imshow("dst1 show", dst1)
cv2.imshow("dst show", dst)
cv2.waitKey(0)

X上效果:

opencv存储rgb格式为png图片 opencv支持的图片格式_中值滤波_20


Y上的效果:

opencv存储rgb格式为png图片 opencv支持的图片格式_高斯滤波_21


相加效果:

opencv存储rgb格式为png图片 opencv支持的图片格式_opencv存储rgb格式为png图片_22

Scharr算子

scharr算子是sobel的一种改进版本,实际上是将提取的效率提升了几倍

opencv存储rgb格式为png图片 opencv支持的图片格式_卷积核_23

opencv存储rgb格式为png图片 opencv支持的图片格式_卷积核_24


实现代码和效果:

opencv存储rgb格式为png图片 opencv支持的图片格式_高斯滤波_25