Python OpenCV基础学习笔记

本文详细介绍了OpenCV在图像处理中的基本操作,包括色彩空间转换(如BGR到灰度、HSV),图像对象创建、赋值与复制,像素读写及算数操作,使用TrackBar调整图像亮度和对比度,键盘响应操作,颜色表应用,像素逻辑操作,通道分离与合并,几何形状绘制,随机颜色生成,多边形填充,图像翻转、旋转与缩放,以及视频和直方图处理。内容涵盖了OpenCV图像处理的多个核心知识点。
摘要由CSDN通过智能技术生成

OpenCV学习笔记

图像色彩空间转换

jpg图片的色彩空间为RGB,png图片多一个透明通道,OpenCV读取到的图像色彩空间为BGR

色彩空间转换方法

gary = cv.cvtColor(image, cv.COLOR_BGR2GRAY)  # 转换为灰度
hsv = cv.cvtColor(image, cv.COLOR_BGR2HSV)  # 转换为hsv
hsv = cv.cvtColor(image, cv.COLOR_HSV2BGR)  # hsv转换为BGR,H通道范围为0-180,其余为0-255

图像对象的创建于赋值

image = cv.imread("D:/Code/1.jpg")  # (666, 999, 3)
    print(image.shape)  # 输出图片的高,宽,通道 h, w, c
    roi = image[60:200, 50:100, :]  # 将图片一部分区域设置为roi区域
    blank = np.zeros_like(image)  # 创建一个和图片一样大小的空白图片
    blank[60:200, 50:100, :] = image[60:200, 60:110, :]  # 将图片的一部分拷贝到空白图片中

两种复制图像方法的区别

blank = np.copy(image)

这种方法复制的图片,是通过copy方法将image图片复制在blank下,对blank的操作不影响image

blank = image

这种方法相当于blank和image为同一个数据,对blank修改后都会同时影响两个的图像数据

图像像素的读写操作

将图像进行反色操作

h, w, c = image.shape
    for row in range(h):
        for col in range(w):
            b, g, r = image[row, col]
            image[row, col] = (255 - b, 255 - g, 255 - r)

图像像素的算数操作

在做两个图像像素运算时,要保证两个图片的大小和通道数都一致,才能进行运算

image = cv.imread("D:/Code/1.jpg")  # (666, 999, 3)
cv.imshow("input", image)
blank = np.zeros_like(image)
blank[:, :] = (10, 10, 10) # 为blank图像像素的通道赋值
cv.imshow("blank", blank)
result = cv.add(image, blank)  # 相加
result = cv.subtract(image, blank)  # 相减
result = cv.multiply(image, blank)  # 相乘
result = cv.divide(image, blank)  # 相除

TrackBar滚动条操作调整亮度

def print_value(a):
    print(a)

def adjust_lightness_demo():
    image = cv.imread("D:/Code/1.jpg")  # (666, 999, 3)
    cv.namedWindow("input", cv.WINDOW_AUTOSIZE)  # 创建窗口 (窗口名,窗口大小自适应图片大小并且不能更改)
    cv.createTrackbar("lightness", "input", 0, 255, print_value)  # 创建滚动条 (滚动条名字,滚动条属于的窗口名字,滚动条取值范围,回调函数)
    cv.imshow("input", image)
    blank = np.zeros_like(image)
    while True:
        pos = cv.getTrackbarPos("lightness", "input")  # 获取当前滚动条的值
        blank[:, :] = (pos, pos, pos)
        result = cv.add(image, blank)
        cv.imshow("result", result)
        c = cv.waitKey(1)  # 等待用户触发事件时间
        if c == 27:  # 如果按下ESC(ASCII码为27)
            cv.destroyAllWindows()
cv.namedWindow(winname, flags=None)
  • winname:创建的窗口名字
  • flags:WINDOW_AUTOSIZE 窗口大小自动适应图片大小,并且不可手动更改。
    WINDOW_NORMAL 用户可以改变这个窗口大小
    WINDOW_OPENGL 窗口创建的时候会支持OpenGL

TrackBar滚动条操作调整对比度

def adjust_contrast_demo():
    image = cv.imread("D:/Code/1.jpg")  # (666, 999, 3)
    cv.namedWindow("input",cv.WINDOW_AUTOSIZE)
    cv.createTrackbar("lightness", "input", 0, 255, print_value)
    cv.createTrackbar("contrast", "input", 0, 255, print_value)
    cv.imshow("input", image)
    blank = np.zeros_like(image)
    while True:
        light = cv.getTrackbarPos("lightness", "input")
        contrast = cv.getTrackbarPos("contrast", "input")/100
        print("light:", light, ",contrast:", contrast)
        result = cv.addWeighted(image, contrast, blank, 0, light)
        cv.imshow("result", result)

cv.addWeighter(src1, alpha, src2, beta, gamma, dst=None, dtype=None)
  • src1:第一个原数组
  • alpha,第一个数组元素权重
  • src2第二个原数组
  • beta,第二个数组元素权重
  • gamma,图1与图2作和后添加的数值。不要太大,不然图片一片白。总和等于255以上就是纯白色了
  • dst,输出图片

键盘响应操作

def keys_demo():
    image = cv.imread("D:/Code/1.jpg")  # (666, 999, 3)
    cv.namedWindow("input", cv.WINDOW_AUTOSIZE)  # 创建窗口 (窗口名,窗口大小自适应图片大小并且不能更改)
    cv.imshow("input", image)
    while True:
        c = cv.waitKey(1)  # 等待用户触发事件时间
        if c == 49:  # 按键1
            gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
            cv.imshow("result", gray)
        if c == 50:  # 按键2
            hsv = cv.cvtColor(image, cv.COLOR_BGR2HSV)
            cv.imshow("result", hsv)
        if c == 27:  # 如果按下ESC(ASCII码为27)
            cv.destroyAllWindows()

OpenCV自带颜色表操作

def color_table_demo():
    colormap = [
        cv.COLORMAP_AUTUMN,
        cv.COLORMAP_BONE,
        cv.COLORMAP_JET,
        cv.COLORMAP_WINTER,
        cv.COLORMAP_RAINBOW,
        cv.COLORMAP_OCEAN,
        cv.COLORMAP_SUMMER,
        cv.COLORMAP_SPRING,
        cv.COLORMAP_COOL,
        cv.COLORMAP_PINK,
        cv.COLORMAP_HOT,
        cv.COLORMAP_PARULA,
        cv.COLORMAP_MAGMA,
        cv.COLORMAP_INFERNO,
        cv.COLORMAP_PLASMA,
        cv.COLORMAP_VIRIDIS,
        cv.COLORMAP_CIVIDIS,
        cv.COLORMAP_TWILIGHT,
        cv.COLORMAP_TWILIGHT_SHIFTED]
    image = cv.imread("D:/Code/1.jpg")  # (666, 999, 3)
    cv.namedWindow("input", cv.WINDOW_AUTOSIZE)  # 创建窗口 (窗口名,窗口大小自适应图片大小并且不能更改)
    cv.imshow("input", image)
    index = 0
    while True:
        dst = cv.applyColorMap(image, colormap[index % 19])
        index += 1
        cv.imshow("result", dst)
        c = cv.waitKey(200)  # 等待用户触发事件时间
        if c == 27:  # 如果按下ESC(ASCII码为27)
            break
    cv.destroyAllWindows()

图像像素的逻辑操作

def bitwise_demo():
    b1 = np.zeros((400, 400, 3), dtype=np.uint8)
    b1[:, :] = (255, 0, 255)
    b2 = np.zeros((400, 400, 3), dtype=np.uint8)
    b2[:, :] = (0, 255, 255)
    cv.imshow("b1", b1)
    cv.imshow("b2", b2)
    dst1 = cv.bitwise_and(b1, b2)  # 与运算
    dst2 = cv.bitwise_or(b1, b2)  # 或运算
    cv.imshow("bitwise_and", dst1)
    cv.imshow("bitwise_or", dst2)
    cv.waitKey(0)

通道分离与合并

def channels_split_demo():
    b1 = cv.imread("D:/Code/1.jpg")
    print(b1.shape)
    cv.imshow("input", b1)
    cv.imshow("b1", b1[:, :, 2])
    mv = cv.split(b1)
    mv[0][:, :] = 255  # 将第一通道的值都改为255
    result = cv.merge(mv)  # 将第一通道合并到图像中
    cv.imshow("result", result)
    cv.waitKey(0)
    cv.destroyAllWindows()

图像色彩空间转换

请添加图片描述

def color_space_demo():
    b1 = cv.imread("src/1.jpg")
    print(b1.shape)
    cv.imshow("input", b1)
    hsv = cv.cvtColor(b1, cv.COLOR_BGR2HSV)
    print(hsv)
    cv.imshow("hsv", hsv)
    mask = cv.inRange(hsv, (0, 30, 46), (25, 255, 255))  # 将图像中颜色在第二个参数和第三个参数范围内的颜色设为0,其余为1
    # cv.bitwise_not(mask, mask)  # 自身取反
    result = cv.bitwise_and(b1, b1, mask=mask)  # mask:指定操作范围
    cv.imshow("mask", mask)
    cv.imshow("result", result)
    cv.waitKey(0)
    cv.destroyAllWindows()
cv.inRange(src, lowerb, upperb, dst=None)
  • src:图片
  • lowerb:图像中低于lowerb的值,图像值变为0
  • upperb:是图像中高于upperb的值,图像值变为0

图像像素值统计

def pixel_stat_demo():
    # b1 = cv.imread("src/1.jpg")
    b1 = np.zeros((512, 512, 3), dtype=np.uint8)
    print(b1.shape)
    cv.imshow("input", b1)
    means, dev = cv.meanStdDev(b1)  # 均值,方差
    print("means:", means, "dev:", dev)
    cv.waitKey(0)
    cv.destroyAllWindows()

图像几何形状绘制

def drawing_demo():
    b1 = np.zeros((512, 512, 3), dtype=np.uint8)
    cv.rectangle(b1, (50, 50), (400, 400), (0, 0, 255), 2, 8, 0)
    cv.circle(b1, (225, 225), 175, (255, 0, 0), -1, 8, 0)
    cv.line(b1, (50, 50), (400, 400), (0, 255, 0), 2, 8, 0)
    # b1[:,:] = 0
    cv.putText(b1, "This is a text", (50, 50), cv.FONT_HERSHEY_SIMPLEX, 1.0, (0, 255, 255), 2, 8)
    cv.imshow("result", b1)
    cv.waitKey(0)
    cv.destroyAllWindows()
cv.rectangle(img, pt1, pt2, color, thickness=None, lineType=None, shift=None)
  • img:所绘制的图片
  • pt1:矩形的左上角坐标
  • pt2:矩形的右下角坐标
  • color:矩形颜色(bgr)
  • thickness:线条粗细,-1时为填充
  • lineType:
  • shift:点坐标中的分数位的偏移数
cv.circle(img, center, radius, color, thickness=None, lineType=None, shift=None)
  • img:所绘制的图片
  • center:圆心坐标
  • radius:半径
  • color:颜色(bgr)
  • thickness:线条粗细,-1时为填充
  • lineType:
  • shift:点坐标中的分数位的偏移数
cv.line(img, pt1, pt2, color, thickness=None, lineType=None, shift=None)
  • img:所绘制的图片
  • pt1:起点坐标
  • pt2:终点坐标
  • color:颜色(bgr)
  • thickness:线条粗细,不能取负值
  • lineType:
  • shift:点坐标中的分数位的偏移数
cv.putText(img, text, org, fontFace, fontScale, color, thickness=None, lineType=None, bottomLeftOrigin=None)
  • img:所绘制的图片
  • text:文本内容
  • org:文本左上角坐标
  • fontFace:字体
  • fontScale:字号
  • thickness:线条粗细,不能取负值
  • lineType:
  • bottomLeftOrigin:如果为true,则图像数据原点位于左下角。 否则它位于左上角

随机数与随机颜色

def random_color_demo():
    b1 = np.zeros((512, 512, 3), dtype=np.uint8)
    while True:
        xx = np.random.randint(0, 512, 2, dtype=np.int)
        yy = np.random.randint(0, 512, 2, dtype=np.int)
        bgr = np.random.randint(0, 255, 3, dtype=np.int32)
        cv.line(b1, (xx[0], yy[0]), (xx[1], yy[1]), (np.int(bgr[0]), np.int(bgr[1]), np.int(bgr[2])), 1, 8, 0)
        cv.imshow("result", b1)
        c = cv.waitKey(1)
        if c == 27:
            break
    cv.destroyAllWindows()
np.random.randint(low, high=None, size=None, dtype=None)
  • low:最小值
  • high:最大值
  • size:生成随机数的数量
  • dtype:随机数类型

多边形填充与绘制

def polyline_drawing_demo():
    canvas = np.zeros((512, 512, 3), dtype=np.uint8)
    pts = np.array([[100, 100], [300, 100], [450, 200], [320, 450], [80, 400]])
    # cv.fillPoly(canvas, [pts], (255, 0, 255), 8, 0)
    # cv.polylines(canvas, [pts], True, (0, 0, 255), 2, 8, 0)
    cv.drawContours(canvas, [pts], -1, (255, 0, 0), -1)  # 可实现前两个函数功能,最后一个参数为-1时填充,正数时不填充

函数中的[pts]是因为可以同时绘制多组点,所以在函数中以数组形式作为参数,如需绘制多点,则参数为[pts1, pts2, pts3, …]

鼠标操作与响应

b1 = cv.imread("D:/Code/py/OpenCV/src/1.jpg")
img = np.copy(b1)
x1 = -1
x2 = -1
y1 = -1
y2 = -1

def mouse_drawing(event, x, y, flags, param):
    global x1, x2, y1, y2
    if event == cv.EVENT_LBUTTONDOWN:
        x1 = x
        y1 = y
    if event == cv.EVENT_MOUSEMOVE:
        if x1 < 0 or y1 < 0:
            return
        x2 = x
        y2 = y
        b1[:, :, :] = img[:, :, :]
        cv.rectangle(b1, (x1, y1), (x2, y2), (0, 0, 255), 2, 8, 0)
    if event == cv.EVENT_LBUTTONUP:
        if x1 < 0 or y1 < 0:
            return
        x2 = x
        y2 = y
        b1[:, :, :] = img[:, :, :]
        cv.rectangle(b1, (x1, y1), (x2, y2), (0, 0, 255), 2, 8, 0)
        x1 = -1
        x2 = -1
        y1 = -1
        y2 = -1

def mouse_demo():
    cv.namedWindow("mouse_demo", cv.WINDOW_AUTOSIZE)
    cv.setMouseCallback("mouse_demo", mouse_drawing)
    while True:
        cv.imshow("mouse_demo", b1)
        c = cv.waitKey(1)
        if c == 27:
            break
    cv.destroyAllWindows()

图像像素类型转换与归一化

def norm_demo():
    image = cv.imread("D:/Code/py/OpenCV/src/1.jpg")
    cv.namedWindow("norm_demo", cv.WINDOW_AUTOSIZE)
    result = np.zeros_like(np.float32(image))  # 将图片转化为浮点型
    cv.normalize(np.float32(image), result, 0, 1, cv.NORM_MINMAX, dtype=cv.CV_32F)  # 第二种方法将图片转换为浮点型
    cv.imshow("norm_demo", np.uint8(result * 255))  # 将图片数据类型还原
    cv.waitKey(0)
    cv.destroyAllWindows()

为什么需要将图片像素类型转为浮点
例如在深度学习当中,需要大量的浮点运算,所以将图片像素类型也转为浮点后可进行更精准的计算

图像缩放与差值

def resize_demo():
    image = cv.imread("D:/Code/py/OpenCV/src/1.jpg")
    h, w, c = image.shape
    cv.namedWindow("resize", cv.WINDOW_AUTOSIZE)
    dst = cv.resize(image, (0, 0), fx=0.75, fy=0.5, interpolation=cv.INTER_NEAREST)
    cv.imshow("resize", dst)
    cv.waitKey(0)
    cv.destroyAllWindows()
cv.resize(src, dsize, dst=None, fx=None, fy=None, interpolation=None)
  • src:需要进行缩放的图像
  • dsize:需要缩放到的尺寸(h,w)只能为整数,如果为(0,0),则可以指定fx和fy参数进行倍数缩放
  • fx:图像宽的缩放倍数
  • fy:图像高的缩放倍数
  • interpolation:图像缩放算法
    INTER_NEAREST - 最邻近插值
    INTER_LINEAR - 双线性插值,如果最后一个参数你不指定,默认使用这种方法
    INTER_AREA - resampling using pixel area relation. It may be a preferred method for image decimation, as it gives moire’-free results. But when the image is zoomed, it is similar to the INTER_NEAREST method.
    INTER_CUBIC - 4x4像素邻域内的双立方插值
    INTER_LANCZOS4 - 8x8像素邻域内的Lanczos插值

图像翻转

def flip_demo():
    image = cv.imread("D:/Code/py/OpenCV/src/1.jpg")
    cv.imshow("image", image)
    cv.namedWindow("flip", cv.WINDOW_AUTOSIZE)
    dst = cv.flip(image, 0)
    cv.imshow("flip", dst)
    cv.waitKey(0)
    cv.destroyAllWindows()
cv.flip(src, flipCode, dst=None)
  • src:输入图像
  • flipCode:翻转形式
    -1:水平,垂直方向同时翻转
    0:垂直方向翻转
    1:水平方向翻转

图像旋转

相关文章

https://mp.weixin.qq.com/s?__biz=MzA4MDExMDEyMw==&mid=2247490762&idx=2&sn=e5ebc3894ce5ca668dca58c60e1fe63c&chksm=9fa86b8ea8dfe29805b3a92ce3d6a4a2ebf53a1fecd49bffff017463cacf12693847c40acfab&token=75388548&lang=zh_CN#rd

def rotate_demo():
    src = cv.imread("D:/Code/py/OpenCV/src/1.jpg")
    h, w, c = src.shape
    M = np.zeros((2, 3), dtype=np.float32)
    alpha = np.cos(np.pi / 4.0)
    beta = np.sin(np.pi / 4.0)
    print("alpha : ", alpha)

    # 初始旋转矩阵
    M[0, 0] = alpha
    M[1, 1] = alpha
    M[0, 1] = beta
    M[1, 0] = -beta
    cx = w / 2
    cy = h / 2
    tx = (1 - alpha) * cx - beta * cy
    ty = beta * cx + (1 - alpha) * cy
    M[0, 2] = tx
    M[1, 2] = ty

    # change with full size
    bound_w = int(h * np.abs(beta) + w * np.abs(alpha))
    bound_h = int(h * np.abs(alpha) + w * np.abs(beta))

    # 添加中心位置迁移
    M[0, 2] += bound_w / 2 - cx
    M[1, 2] += bound_h / 2 - cy
    dst = cv.warpAffine(src, M, (bound_w, bound_h))
    cv.imshow("rotate without cropping", dst)
    cv.waitKey(0)
    cv.destroyAllWindows()

视频文件/摄像头使用

def video_demo():
    cap = cv.VideoCapture(0)
    w = cap.get(cv.CAP_PROP_FRAME_WIDTH)  # 获取视频的宽
    h = cap.get(cv.CAP_PROP_FRAME_HEIGHT)  # 获取视频的高
    fps = cap.get(cv.CAP_PROP_FPS)  # 获取视频的帧数
    print(w, h, fps)
    while True:
        ret, frame = cap.read()
        frame = cv.flip(frame,1)
        if ret is True:
            cv.imshow("frame", frame)
            c = cv.waitKey(10)  # 读取视频时,等待时间决定播放的快慢
            if c == 27:
                break
    cv.destroyAllWindows()
cv.VideoCapture()
  • 参数为数字,调用系统摄像头,数字表示为摄像头编号
  • 参数为路径,表示读取视频文件

图像直方图

import matplotlib.pyplot as plt  # 需要导入matplotliib库作图

def image_hist():
    image = cv.imread("D:/Code/py/OpenCV/src/1.jpg")
    cv.imshow("image", image)
    color = ("blue", "green", "red")
    for i, color in enumerate(color):
        hist = cv.calcHist([image], [i], None, [256], [0, 256])
        print(hist)
        plt.plot(hist, color=color)
        plt.xlim([0, 256])
    plt.show()
    cv.waitKey(0)
    cv.destroyAllWindows()
cv.calcHist(images, channels, mask, histSize, ranges, hist=None, accumulate=None)
  • images:输入的图像,需要用[]括起来
  • channels:计算直方图的通道
  • mask:遮罩,None为处理整张图像
  • histSize:表示直方图被分成多少份,就是多少个柱
  • ranges:直方图中各个像素的值

二维直方图

def hist2d_demo():
    image = cv.imread("D:/Code/py/OpenCV/src/1.jpg")
    hsv = cv.cvtColor(image, cv.COLOR_BGR2HSV)
    hist = cv.calcHist([hsv], [0, 1], None, [48, 48], [0, 180, 0, 256])
    dst = cv.resize(hist, (400, 400))
    cv.normalize(dst, dst, 0, 255, cv.NORM_MINMAX)
    cv.imshow("image", image)
    dst = cv.applyColorMap(np.uint8(dst), cv.COLORMAP_JET)
    cv.imshow("hist", dst)
    plt.imshow(hist, interpolation='nearest')
    plt.title("2D Histogram")
    plt.show()
    cv.waitKey(0)
    cv.destroyAllWindows()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

昕zqx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值