opencv-python的图像变换、绘图、滑动条、鼠标事件笔记记录

 


一、图像变换

1.图片缩放

cv2.resize(),可以直接按照大小缩放,也可以按照比例缩放。

点击查看代码
import cv2

img = cv2.imread('lena.bmp')
# 按照指定的宽度、高度缩放图片
res = cv2.resize(img, (132, 150))
# 按照比例缩放,如x,y轴均放大一倍
res2 = cv2.resize(img, None, fx=2, fy=2, interpolation=cv2.INTER_LINEAR)
cv2.imshow('shrink', res), cv2.imshow('zoom', res2)
cv2.waitKey(0)

2.图片平移

cv2.warpAffine()使用仿射变换的函数实现平移,函数的第二个参数就是变换矩阵,主要就是用这个矩阵进行变换。

  • 仿射变换后,原图中平行的线依然平行
  • 用cv2.warpAffine()实现仿射变换
  • 仿射变换需要定义一个2*3维的变换矩阵
点击查看代码
import cv2

# 读取图片
img = cv2.imread('lena.jpg')
# 平移图片
rows, cols = img.shape[:2]
# 定义平移矩阵,需要是numpy的float32类型
# x轴平移100,y轴平移50
M = np.float32([[1, 0, 100], [0, 1, 50]])
# 用仿射变换实现平移
dst = cv2.warpAffine(img, M, (cols, rows))
cv2.imshow('shift', dst)
cv2.waitKey(0)

3.图片旋转

使用cv2.getRotationMatrix2D()函数来获取旋转矩阵M(2x3)的参数。(其实像上面图片平移中的代码那样自己手动设定M矩阵也是可以的,只不过自己计算矩阵M比较麻烦)
然后同样也是使用仿射变换的函数cv2.warpAffine()进行旋转。

点击查看代码
import cv2

# 读取图片
img = cv2.imread('lena.jpg')

# 45°旋转图片并缩小一半
rows, cols = img.shape[:2]
M = cv2.getRotationMatrix2D((cols / 2, rows / 2), 45, 0.5)
dst = cv2.warpAffine(img, M, (cols, rows))
cv2.imshow('rotation', dst)
cv2.waitKey(0)

通过几个点计算得到矩阵M,可以使用cv2.getAffineTransform()函数。

点击查看代码
import cv2

# 读取图片
img = cv2.imread('lena.jpg')

# 变换前的三个点
Point1 = np.float32([[50, 50], [100, 60], [150, 700]])
# 变换后的三个点
Point2 = np.float32([[50, 100], [150, 60], [ 100, 200]])
# 生成变换矩阵
M = cv2.getAffineTransform(Point1 , Point2 )

4.透视变换

主要作用就是校正图片的作用,如下图:

点击查看代码
import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread('case1r.png')

rows, cols = img.shape[:2]
# 原图中需要校正的四个角点
pts1 = np.float32([[5, 321], [323, 5], [455, 769], [769, 453]])
# 变换后分别在左上、右上、左下、右下四个点
pts2 = np.float32([[0, 0], [320, 0], [0, 480], [320, 480]])
# 生成透视变换矩阵
M = cv2.getPerspectiveTransform(pts1, pts2)
# 进行透视变换
dst = cv2.warpPerspective(img, M, (320, 480))

# 用cv的函数显示
cv2.imshow('raw', img)
cv2.imshow('dst', dst)
cv2.waitKey(0)

# 用matplotlib显示
plt.subplot(121), plt.imshow(img[:, :, ::-1]), plt.title('input')
plt.subplot(122), plt.imshow(dst[:, :, ::-1]), plt.title('output')
plt.show()

获取需要矫正的图片的四个点可以通过鼠标右击,启动图片编辑功能,然后得到图片的四个角点。
也可以通过鼠标事件相关的代码,通过鼠标点击获得图片的四个角点坐标,以下是通过鼠标事件相关的代码点击获取:

点击查看代码
import cv2

# 鼠标的回调函数
def mouse_event(event, x, y, flags, param):
    # 通过event判断具体是什么事件,这里是左键按下
    if event == cv2.EVENT_LBUTTONDOWN:
        print((x, y))

def main():
    img = cv2.imread('case1r.png')
    cv2.namedWindow('image')
    # 定义鼠标的回调函数
    cv2.setMouseCallback('image', mouse_event)
    while (True):
        cv2.imshow('image', img)
        # 按下ESC键退出
        if cv2.waitKey(20) == 27:
            break


if __name__ == '__main__':
    main()

二、绘图

  • 创建黑色的底图:img = np.zeros((640, 480, 3), np.uint8)
  • 画直线:cv2.line()
  • 画矩形:cv2.rectangle()
  • 画圆:cv2.circle()
  • 画半圆:'cv2.ellipse()'
  • 写字:putText(img, text, org, fontFace, fontScale, color, thickness=None, lineType=None, bottomLeftOrigin=None)

使用cv2.polylines()函数绘制多边形

点击查看代码
import cv2
import numpy as np

# 创建黑色底图
img = np.zeros((640, 480, 3), np.uint8)

# 定义多边形的几个点
points = np.array([[10, 5],  [50, 10], [70, 20], [20, 30]], np.int32)
# 将顶点坐标转换成4*1*2维
points = points.reshape((-1, 1, 2))
cv2.polylines(img, [pts], True, (0, 255, 255))
# 显示
cv2.imshow('img', img)

三、滑动条

滑动条操作主要涉及到两个函数:
cv2.createTrackbar(trackbarName, windowName, value, count, onChange)

  • trackbarName : 滑动条的名称
  • windowName : 滑动条所在的窗口
  • value : 滑块的起始值
  • count : 滑块的最大值
  • onChange : 回调函数,即当滑块位置改变时就会调用的函数,并且回调函数第一个参数为滑块位置所对应的值

cv2.getTrackbarPos(trackbarname, winname)

  • trackbarname : 选择的滑动条名称
  • winname : 选择的滑动条所在窗口的名称

不使用回调函数:

点击查看代码
import cv2
import numpy as np
# 创建一个(500,500)的numpy数组
img=np.zeros((500, 500), dtype='uint8')

# 新建一个窗口
cv2.namedWindow('img')

# 定义回调函数,这里pass表示不做任何事,用作占位语句保持程序结构的完整性
def trackBar(x):
    pass

# 新建一个滑动条
cv2.createTrackbar('color', 'img', 0 , 255, trackBar)

while(True):
    cv2.imshow('img', img)

    # 返回滑块所在位置对应的值
    color = cv2.getTrackbarPos('color','img')
    img[:] = [color]

    if cv2.waitKey(1) == ord('q'):
        break

cv2.destroyAllWindows()

使用回调函数:

点击查看代码
import cv2
import numpy as np
# 创建一个(500,500)的numpy数组
img=np.zeros((500, 500), dtype='uint8')
# 新建一个窗口
cv2.namedWindow('img')
# 定义回调函数,参数x为函数cv2.createTrackbar()传递的滑块位置对应的值
def img_intensity_change(x):
    img[:] = [x]
# 新建一个滑动条
cv2.createTrackbar('color','img',0,255,img_intensity_change)
while(True):
    cv2.imshow('img', img)
    if cv2.waitKey(1) == ord('q'):
        break
cv2.destroyAllWindows()

四、鼠标事件

鼠标事件主要涉及到cv2.setMouseCallback(windowName, onMouse, param=None)函数,然后鼠标事件主要在函数的onMouse参数下添加回调函数来完成,另外param参数可以进行像图片参数的传递,这里就可以在回调函数中直接在图上画画。

鼠标点击获取像素点位置的代码:

点击查看代码
import cv2

# 鼠标的回调函数
def mouse_event(event, x, y, flags, param):
    # 通过event判断具体是什么事件,这里是左键按下
    if event == cv2.EVENT_LBUTTONDOWN:
        print((x, y))

def main():
    img = cv2.imread('case1r.png')
    cv2.namedWindow('image')
    # 定义鼠标的回调函数
    cv2.setMouseCallback('image', mouse_event)
    while (True):
        cv2.imshow('image', img)
        # 按下ESC键退出
        if cv2.waitKey(20) == 27:
            break


if __name__ == '__main__':
    main()

五、功能综合demo

主要实现在图上画框,并且可以实现用滑动条选择框的颜色和粗细,另外画框的时候框的大小随时变化,可以实时画框(实现就是在鼠标事件中加了一个把鼠标上一次画的框用底色覆盖的函数,在第40行),滑动条的参数使用全局变量来处理的。

点击查看代码
import cv2
import numpy as np
drawing = False  # 是否开始画图
mode = True  # True:画矩形,False:画圆
start = (-1, -1)
px, py = -1, -1
r, g, b = 0, 255, 0
penSize = 1

def mouse_event(event, x, y, flags, img):
    global start, drawing, mode
    # 左键按下:开始画图
    if event == cv2.EVENT_LBUTTONDOWN:
        drawing = True
        start = (x, y)
    # 鼠标移动,画图
    elif event == cv2.EVENT_MOUSEMOVE:
        if drawing:
            if mode:
                cv2.rectangle(img, start, (x, y), (0, 255, 0), 1)
            else:
                cv2.circle(img, (x, y), 5, (0, 0, 255), -1)
    # 左键释放:结束画图
    elif event == cv2.EVENT_LBUTTONUP:
        drawing = False
        if mode:
            cv2.rectangle(img, start, (x, y), (0, 255, 0), 1)
        else:
            cv2.circle(img, (x, y), 5, (0, 0, 255), -1)
# 鼠标画框
def my_mouse_event(event, x, y, flags, img):
    global start, drawing, mode, px, py
#     左键按下获取起点坐标
    if event == cv2.EVENT_LBUTTONDOWN:
        drawing = True
        start = (x, y)
    elif event == cv2.EVENT_MOUSEMOVE:
        if drawing:
            if mode:
                cv2.rectangle(img, start, (px, py), (0, 0, 0), penSize)
                cv2.rectangle(img, start, (x, y), (r, g, b), penSize)
                px, py = x, y
            else:
                cv2.circle(img, (x, y), 5, (0, 0, 255), -1)
    # 左键释放:结束画图
    elif event == cv2.EVENT_LBUTTONUP:
        drawing = False
        if mode:
            cv2.rectangle(img, start, (x, y), (r, g, b), penSize)
        else:
            cv2.circle(img, (x, y), 5, (0, 0, 255), -1)

def trackbar(x):
    pass

def main():
    global r, g, b, penSize
    img = np.zeros((512, 512, 3), np.uint8)
    cv2.namedWindow('image')

    # 创建 RGB 三个滑动条
    cv2.createTrackbar('R', 'image', 0, 255, trackbar)
    cv2.createTrackbar('G', 'image', 0, 255, trackbar)
    cv2.createTrackbar('B', 'image', 0, 255, trackbar)
    cv2.createTrackbar('penSize', 'image', 1, 5, trackbar)

    # cv2.setMouseCallback('image', mouse_event, img)
    cv2.setMouseCallback('image', my_mouse_event, img)
    while (True):
        cv2.imshow('image', img)
        # 获取滑块的值
        r = cv2.getTrackbarPos('R', 'image')
        g = cv2.getTrackbarPos('G', 'image')
        b = cv2.getTrackbarPos('B', 'image')
        penSize = cv2.getTrackbarPos('penSize', 'image')

        # 按下m切换模式
        if cv2.waitKey(1) == ord('m'):
            mode = not mode
        elif cv2.waitKey(1) == 27:
            break

if __name__ == '__main__':
    main()
posted @   乞力马扎罗山的雪  阅读(532)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示

目录导航