OpenCV学习+常用函数记录①:图像的基本处理

2020-11-24 10:51:58 浏览数 (1)

OpenCV 图像的基本处理

    • 1.1 图片读取和显示
    • 1.2 写入文件(保存)
    • 1.3 像素操作
    • 1.4 图片剪切
    • 1.5 镜像处理:
    • 1.6 图像缩放
    • 1.7 图像位移
    • 1.8 图像旋转
    • 1.9 仿射变换
    • 1.10 图像融合
    • 1.11 灰度处理
    • 1.12 颜色反转
    • 1.13 马赛克
    • 1.14 毛玻璃
    • 1.15 浮雕效果
    • 1.16 图形绘制
    • 1.17 亮度增强
    • 1.18 直方图均衡化
    • 1.19 视频处理
    • 1.20 HSV颜色空间
    • 1.21 阈值处理
    • 1.22 人脸识别
  • 最近因项目需要加上自己的兴趣,需要用一些opencv相关的东西,虽然之前零零碎碎学习过一些,但是很久不用就忘了,打算写篇文章总结一下学习的过程以及一些常用的函数。类似的博文有很多,但还是觉得自己总结一编印象深一些。

1.1 图片读取和显示

读取:cv.imread(“图片路径”, “读取的方式”)

显示:cv.imshow(“窗口名称”, “图片数据”)

  • 读取方式: 分别有如下三种: cv.IMREAD_COLOR : 以彩图的方式加载,会忽略透明度(默认方式) cv.IMREAD_GRAYSCALE: 以灰色图片方式加载 cv.IMREAD_UNCHANGED: 直接加载,透明度会得到保留

例:

代码语言:javascript复制
import cv2 as cv

# 读取图片 参数1:图片路径, 参数2:读取的方式 
img = cv.imread("img/lena.png", cv.IMREAD_COLOR)
# 显示窗口 参数1:窗口名称, 参数2:图片数据
cv.imshow("src", img)

# 让程序处于等待推出状态
cv.waitKey(0)
# 当程序推出时,释放所有窗口资源
cv.destroyAllWindows()

1.2 写入文件(保存)

代码语言:javascript复制
import cv2 as cv
img = cv.imread("img/lena.png", cv.IMREAD_UNCHANGED)

# 将图片写入到磁盘中,参数1: 图片写入路径,参数2: 图片数据
cv.imwrite("img/lena_copy.png", img)

cv.waitKey(0)
cv.destroyAllWindows()

1.3 像素操作

代码语言:javascript复制
import cv2 as cv
import numpy as np

# 构建一个空白的矩阵
img = np.zeros((30, 40, 3), np.uint8)

# 将第15行所有像素点全都改成红色
for i in range(40):
    # 设置第15行颜色为红色
    img[15, i] = (0, 0, 255)

# 显示图片
cv.imshow("src", img)

cv.waitKey(0)
cv.destroyAllWindows()

1.4 图片剪切

剪切:mat[起始行号:结束行号,开始列号:结束列号]

代码语言:javascript复制
import cv2 as cv

# 读取原图
img = cv.imread("img/lena.jpg", cv.IMREAD_COLOR)
cv.imshow("source", img)
# 从图片(230,230) 截取一张 宽度130,高度70的图片
dstimg = img[180:250, 180:310]
# 显示图片
cv.imshow("result", dstimg)

cv.waitKey(0)

1.5 镜像处理:

获取宽高信息:

代码语言:javascript复制
imgInfo = img.shape
imgInfo[0] : 表示高度
imgInfo[1] : 表示宽度
imgInfo[2] : 表示每个像素点由几个颜色值构成

实现步骤:

  1. 创建一个两倍于原图的空白矩阵
  2. 将图像的数据按照从前向后,从后向前进行绘制
代码语言:javascript复制
import cv2 as cv
import numpy as np

# 创建两倍原图的大小的画布出来
img = cv.imread("../img/lena.jpg")
#  获取图像尺寸
print img.shape
height = img.shape[0]
width = img.shape[1]
print height, width

dst = np.zeros((height * 2, width, 3), np.uint8)

for row in range(height):
    for col in range(width):
        dst[row, col] = img[row, col]

        dst[height*2 - row - 1, col] = img[row, col]

cv.imshow("img", img)
cv.imshow("dst", dst)

cv.waitKey(0)

1.6 图像缩放

关于图片的缩放,常用有两种:

  1. 等比例缩放
  2. 任意比例缩放

图片缩放的常见算法:

  1. 最近领域插值
  2. 双线性插值
  3. 像素关系重采样
  4. 立方插值

默认使用的是双线性插值法,可以利用opencv提供的 resize 方法来进行图片的缩放

代码语言:javascript复制
import cv2 as cv

img = cv.imread("../img/lena.jpg")

cv.imshow("src", img)
height = img.shape[0]
width = img.shape[1]

dst = cv.resize(img, (height*2, width*2))
cv.imshow("dst", dst)

cv.waitKey()

1.7 图像位移

矩阵运算:cv.warpAffine(原始图像,变换矩阵,(高度,宽度))

代码语言:javascript复制
import cv2 as cv
import numpy as np

img = cv.imread("../img/lena.jpg")
height, width = img.shape[0:2]
# 图像的位移
matrixShift = np.float32([[1, 0, 50], [0, 1, 100], ])
# 图像矩阵运算
dst = cv.warpAffine(img, matrixShift, (width, height))
cv.imshow("dst", dst)
cv.waitKey()

1.8 图像旋转

旋转变换:cv.getRotationMatrix2D((旋转中心),旋转角度,缩放系数)

代码语言:javascript复制
import cv2 as cv

img = cv.imread("../img/lena.jpg")
height, width = img.shape[0:2]
# 1.旋转中心, 2.旋转角度, 3. 缩放系数
M = cv.getRotationMatrix2D((width/2, height/2), 45, 0.5);
# 图像矩阵运算
dst = cv.warpAffine(img, M, (width, height));
cv.imshow("dst", dst)
cv.waitKey()

1.9 仿射变换

代码语言:javascript复制
import cv2 as cv
import numpy as np

img = cv.imread("../img/itheima.jpg")
height, width = img.shape[0:2]
# 定义变换的参考点: 左上角,左下角,右上角
matrixSrc = np.float32([[0, 0], [0, height-1], [width-1, 0]]);
# 将上述三个点映射到一个新的坐标系中
matrixDst = np.float32([[50, 100], [300, height-200], [width-300,100]]);
# 计算从Src到Dst的变换矩阵
M = cv.getAffineTransform(matrixSrc, matrixDst);
# 仿射变换
dst = cv.warpAffine(img, M, (width, height))
cv.imshow("src", img)
cv.imshow("dst", dst)
cv.waitKey()

1.10 图像融合

代码语言:javascript复制
import cv2 as cv
import numpy as np

src = cv.imread("../img/itheima.jpg")
tony = cv.imread("../img/tony.jpg")

dst = cv.addWeighted(src, 0.5, tony, 0.5, 100)

cv.imshow("src", src)
cv.imshow("tony", tony)
cv.imshow("dst", dst)

cv.waitKey()

1.11 灰度处理

代码语言:javascript复制
import cv2 as cv

# 方式一 : 直接以灰度图像的形式读取
img = cv.imread("img/itheima.jpg", cv.IMREAD_GRAYSCALE)
cv.imshow("dstImg", img)
cv.waitKey(0)

# 方式二: 以彩图的方式读取
img = cv.imread("img/itheima.jpg", cv.IMREAD_COLOR)
# 将原图的所有颜色转成灰色
dstImg = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
cv.imshow("dstImg", dstImg)

cv.waitKey(0)

原理演示

代码语言:javascript复制
import cv2 as cv
import numpy as np

src = cv.imread("../img/lena.jpg")
height, width = src.shape[0:2]

# 创建一个画布  0-255   0-255
dst = np.zeros((height, width, 1), np.uint8)

for row in range(height):
    for col in range(width):
        b, g, r = src[row, col]
        # gray = (int(b)   int(g)   int(r))/3
        # 0.299∗color.r   0.587∗color.g   0.114∗color.b
        gray = int(b) * 0.114   int(g) * 0.587   int(r) * 0.299
        # 将计算出来的灰度值填充到画布中
        dst[row, col] = gray

cv.imshow("dst", dst)
cv.waitKey()

1.12 颜色反转

  • 灰图反转
代码语言:javascript复制
import cv2 as cv
import numpy as np

src = cv.imread("../img/itheima.jpg")
height, width = src.shape[0:2]
grayImg = cv.cvtColor(src, cv.COLOR_BGR2GRAY)

cv.imshow("gray1", grayImg)
# 100 ---> 255 - 100 = 155
for row in range(height):
    for col in range(width):
        value = grayImg[row, col]
        grayImg[row, col] = 255 - value

cv.imshow("gray2", grayImg)
cv.imshow("src", src)
cv.waitKey()
  • 彩图反转
代码语言:javascript复制
import cv2 as cv
import numpy as np

src = cv.imread("../img/itheima.jpg")
height, width = src.shape[0:2]

# 创建画布
dst = np.zeros_like(src)

for row in range(height):
    for col in range(width):
        b, g, r = src[row, col]

        dst[row, col] = (255-b, 255-g, 255-r)

cv.imshow("src", src)
cv.imshow("dst", dst)
cv.waitKey()

1.13 马赛克

代码语言:javascript复制
import cv2 as cv
import numpy as np

src = cv.imread('../img/itheima.jpg')
height, width = src.shape[0:2]
# 将图像划分成若干个4*4的小方块,
# 每一个小方块里面的所有像素值修改为和第一个像素块的颜色一样

offset = 10
for row in range(160, 240):
    for col in range(380, 670):
        # 将图像划分成若干个4*4的小方块,
        if row%offset == 0 and col%offset == 0:
            # 获取当前位置的颜色快
            color = src[row, col]
            # 每一个小方块里面的所有像素值修改为和第一个像素块的颜色一样
            for i in range(offset):
                for j in range(offset):
                    src[row i, col j] = color

cv.imshow("src", src)
cv.waitKey()

1.14 毛玻璃

代码语言:javascript复制
import cv2 as cv
import numpy as np
import random

src = cv.imread("../img/itheima.jpg")
height, width = src.shape[0:2]

offset = 10
# 创建一个和原图同样大小的画布
dst = np.zeros_like(src)

# 处理每一个像素
for row in range(height):
    for col in range(width):
        # 计算当前位置,周围的一个随机数
        # index = random.randint(0,offset);
        # 随机的行号
        randomRow = row   random.randint(0, offset)
        # 随机的列号
        randomCol = col   random.randint(0, offset)

        if randomRow > height - 1:
            randomRow = height - 1
        if randomCol > width - 1:
            randomCol = width - 1
        # 获取随机的周围颜色值
        color = src[randomRow, randomCol]
        # 填充到画布中
        dst[row, col] = color

cv.imshow("dst", dst)
cv.imshow("src", src)
cv.waitKey()

1.15 浮雕效果

代码语言:javascript复制
import cv2 as cv
import numpy as np

src = cv.imread("../img/itheima.jpg")

# 将彩图转成灰度图
grayImg = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
height, width = src.shape[0:2]

# 创建一个空白的矩阵 , 画布
dst = np.zeros_like(grayImg)

for row in range(height):
    for col in range(width - 1):
        # 计算相邻两个像素的差值 , 水平方向
        gray0 = grayImg[row, col]
        gray1 = grayImg[row, col 1]

        # 计算相邻像素的梯度 uint8 0-255
        value = int(gray0) - int(gray1)   120

        if value < 0:
            value = -value
        # 将计算出来的值填充一个新的画布中
        dst[row, col] = value

cv.imshow("src", src)
cv.imshow("dst", dst)
cv.imshow("gray", grayImg)
cv.waitKey()

1.16 图形绘制

代码语言:javascript复制
import cv2 as cv
import numpy as np

src = np.zeros((400, 600, 3), np.uint8)

pt1 = (200, 100)
pt2 = (300, 200)
color = (255, 255, 0)

# 绘制线段 参数2:起始点 参数3:结束点 参数4:颜色 参数5:线条宽度
cv.line(src, pt1, pt2, color, 2)  # 图,zuoshang, youxia, yanse, xiankuan

# 绘制一个矩形 参数2:左上角  参数3:右下角 参数4:颜色  参数5:线条宽度,若为负数,则填充整个矩形
cv.rectangle(src, pt1, pt2, color, 1)

# 绘制圆形 参数2:圆心  参数3:半径  参数4:颜色 参数5:线条宽度,若为负数,则填充整个圆形
cv.circle(src, (400, 200), 50, color, -1)

# 绘制文字 参数2:文字内容  参数3:文字起始左下点
cv.putText(src, "hello", (200, 100), cv.FONT_HERSHEY_SIMPLEX, 2, (255, 0, 255), 2)

# 显示图片
cv.imshow("src", src)
cv.waitKey()

1.17 亮度增强

代码语言:javascript复制
import cv2 as cv
import matplotlib.pyplot as plt

src = cv.imread("../img/itheima.jpg")
height, width = src.shape[0:2]

offset = 90
cv.imshow("src1", src)
for row in range(height):
    for col in range(width):
        b, g, r = src[row, col]

        # 增加亮度
        b = b   offset
        g = g   offset
        r = r   offset

        if b > 255: b = 255
        if g > 255: g = 255
        if r > 255: r = 255

        src[row,col] = (b,g,r)

cv.imshow("src2", src)

# 计算图像直方图
hist = cv.calcHist([src], [0], None, [256], [0, 255])
print hist
plt.plot(hist)
plt.show()
cv.waitKey()

1.18 直方图均衡化

直方图:cv.calcHist(图片,通道,掩膜,数量,值的范围)

直方图均衡化:cv.equalizeHist

代码语言:javascript复制
import cv2 as cv
import matplotlib.pyplot as plt

src = cv.imread("../img/itheima.jpg")
cv.imshow("src", src)
# 将彩色图像拆成3层灰度图像: B通道 G通道 R通道
channels = cv.split(src)

channel_B = cv.equalizeHist(channels[0])
channel_G = cv.equalizeHist(channels[1])
channel_R = cv.equalizeHist(channels[2])

# 将三个通道的结果合并在一起
dst = cv.merge([channel_B, channel_G, channel_R])
cv.imshow("dst", dst)
cv.waitKey()

1.19 视频处理

视频:cv.VideoCapture(路径)

代码语言:javascript复制
import cv2 as cv
import matplotlib.pyplot as plt

capture = cv.VideoCapture("../img/vtest.avi")
print capture.isOpened()

# 获取视频的信息
height = capture.get(cv.CAP_PROP_FRAME_HEIGHT)
width = capture.get(cv.CAP_PROP_FRAME_WIDTH)

# 获取视频的帧率: 1s 切换图片的数量
fps = capture.get(cv.CAP_PROP_FPS)
print("height={}, width={}, fps={}".format(height, width, fps))

# 读视频数据
ok, frame = capture.read()
while ok:
    cv.imshow("frame", frame)
    ok, frame = capture.read()
    
    # 彩色图像直方图均衡化
    channels = cv.split(frame)
    channel_B = cv.equalizeHist(channels[0])
    channel_G = cv.equalizeHist(channels[1])
    channel_R = cv.equalizeHist(channels[2])
    # 将三个通道的结果合并在一起
    dst = cv.merge([channel_B, channel_G, channel_R])
    cv.imshow("dst", dst)

    cv.waitKey(int(1000/fps))

1.20 HSV颜色空间

将RGB图像转成HSV图像

代码语言:javascript复制
hsv = cv.cvtColor(rgb, cv.COLOR_BGR2HSV)

1.21 阈值处理

代码语言:javascript复制
所使用的阈值,结果图片 = cv.threshold(img,阈值,最大值,类型)

代码示例:

代码语言:javascript复制
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np


def onChange(value):
    _, binary = cv.threshold(car, value, 255, cv.THRESH_BINARY_INV)		# 第一个值空,_INV反转颜色
    cv.imshow("binary", binary)


car = cv.imread("../img/car.jpg", cv.IMREAD_GRAYSCALE)

onChange(0)		
# 增加滑动条
cv.createTrackbar("thresh", "binary", 0, 255, onChange)		 # 变量名字,窗口名字,min,max,回调函数

cv.imshow("car", car)
cv.waitKey(0)

1.22 人脸识别

核心API:

代码语言:javascript复制
# 加载已经训练好的特征文件
face_classifier = cv.CascadeClassifier("/haarcascade_frontalface_default.xml")
# 根据特征文件去查找人脸
face_classifier.detectMultiScale(图像, 缩放系数, 至少检验次数)

实现步骤:

  1. 加载特征xml文件
  2. 加载图片
  3. 灰度处理
  4. 判决
  5. 绘制出检测出来的人脸
代码语言:javascript复制
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np

# 第1步:加载xml文件
face_classifier = cv.CascadeClassifier("../img/haarcascade_frontalface_default.xml")
eye_classifier = cv.CascadeClassifier("../img/haarcascade_eye.xml")

# 第2步:加载图片
lena = cv.imread("../img/lena.jpg")

# 第3步:将图片转成灰色图片
lena_gray = cv.cvtColor(lena, cv.COLOR_BGR2GRAY)

# 第4步:使用api进行人脸识别 参数2:缩放系数  参数3:至少要检测几次才算正确
faces = face_classifier.detectMultiScale(lena_gray, 1.3, 3)
print faces		# 返回值:左上点的x,y,宽w,高h

# 第5步:在人脸上绘制矩形
for x, y, w, h in faces:
    # 从灰色图片中找到人脸
    grayFace = lena_gray[y:y h, x:x w]
    colorFace = lena[y:y h, x:x w]
    # 在当前人脸上找到眼睛的位置
    eyes = eye_classifier.detectMultiScale(grayFace, 1.2, 5)

	# 在找到人脸上画矩形
    cv.rectangle(lena, (x, y), (x w, y h), (0, 0, 255), 2)
	# 在眼睛上绘制矩形
    for eye_x, eye_y, eye_w, eye_h in eyes:
        cv.rectangle(colorFace, (eye_x,  eye_y), (eye_x eye_w, eye_y eye_h), (0, 255, 255), 2)

cv.imshow("src", lena)
cv.waitKey()

识别结果如下:

0 人点赞