计算机视觉OpenCv学习系列:第六部分、图像操作-2

第六部分、图像操作-2

    • 第一节、图像几何形状绘制
      • 1.几何形状
      • 2.填充、绘制与着色
      • 3.代码练习与测试
    • 第二节、多边形填充与绘制
      • 1.多边形绘制函数
      • 2.绘制与填充
      • 3.代码练习与测试
    • 第三节、图像像素类型转换与归一化
      • 1.归一化方法与支持
      • 2.归一化函数
      • 3.代码练习与测试
    • 第四节、图像几何变换
      • 1.图像几何变换矩阵
      • 2.函数支持
      • 3.代码练习与测试
    • 学习参考

第一节、图像几何形状绘制

1.几何形状


  • 支持绘制线、矩形、圆形
  • 支持填充矩形、圆形、椭圆
  • 支持绘制文本

注意:绘制只能用英文

几何形状的函数:

相关函数
1.cv.line() # 线
2.cv.circle() # 圆形
3.cv.rectangle() # 矩形
4.cv.ellipse() # 椭圆
5.cv.putText() # 文本
# 相关参数解释:
# img表示输入图像
# color表示颜色,如(255, 0,0)表示蓝色,注意颜色维度要和通道数匹配
# thickness表示线宽, 大于0表示绘制,小于0表示填充
# lineType表示渲染模式, 默认LINE_8, LINE_AA表示反锯齿
# 渲染指的是,绘制一个图的时候会对每个像素点周围4个或8个点进行渲染,常用的是LINE_8
# 反锯齿是另一种渲染方式,使用反锯齿渲染的图片效果更好,但是会比较耗时
# 如果追求用户体验并且计算机带的动就用LINE_AA,如果追求性能就用LINE_8

文本绘制:

  • putText 默认只支持英文
  • org表示文字起始坐标点
  • fontFace表示字体类型
  • fontScale表示字体大小

计算文本区域大小:

# 计算文本区域大小的函数
getTextSize (
text,  # 表示文本信息
fontFace, # 表示字体类型
fontScale, # 表示字体大小
thickness # 表示线宽
) 
# 返回文本信息区域大小,与字体的基线baseline位置

如下图包裹OpenCV-Python的白色框就是文本区域大小

计算机视觉OpenCv学习系列:第六部分、图像操作-2_第1张图片

2.填充、绘制与着色


def draw_demo_1():
    # 创建一个512*512*3大小的图像作为画布
    canvas = np.zeros((512, 512, 3), dtype=np.uint8)
    # (100, 100)是起点坐标,(300, 300)是终点坐标
    # 绘制一个红色矩形
    cv.rectangle(canvas, (100, 100), (300, 300), (0, 0, 255), 2, 8)
    # 填充一个紫色矩形
    cv.rectangle(canvas, (400, 100), (450, 150), (255, 0, 255), -1, 8)
    # 绘制一个蓝色圆形
    cv.circle(canvas, (250, 250), 50, (255, 0, 0), 2, cv.LINE_8)
    # 填充一个蓝色圆形
    cv.circle(canvas, (425, 200), 20, (255, 0, 0), -1, cv.LINE_8)
    # 绘制一个绿色线段,lineType=8指的是8联通线型,涉及到线的产生算法,另一种是lineType=4指的是4联通线型
    cv.line(canvas, (100, 100), (300, 300), (0, 255, 0), 2, 8)
    # 添加一个文本
    cv.putText(canvas, "OpenCV-Python", (100, 100), cv.FONT_HERSHEY_SIMPLEX, 1.0, (255, 0, 255), 2)
    cv.imshow("canvas", canvas)
    cv.waitKey(0)
    cv.destroyAllWindows()

结果示例:右图是矩形的参数列表

计算机视觉OpenCv学习系列:第六部分、图像操作-2_第2张图片

3.代码练习与测试


# 动态显示文本区域
def draw_demo_2():
    # 创建一个512*512*3大小的图像作为画布
    canvas = np.zeros((512, 512, 3), dtype=np.uint8)
    # 深度学习对象检测经典颜色:土耳其蓝(140, 199, 0)
    font_color = (140, 199, 0)
    cv.rectangle(canvas, (100, 100), (300, 300), font_color, 2, 8)

    label_txt = "OpenCV-Python"
    label_txt2 = "Hello world is a nice sentence."
    font = cv.FONT_HERSHEY_SIMPLEX  # 字体选择建议就是cv.FONT_HERSHEY_SIMPLEX 或者 cv.FONT_HERSHEY_PLAIN
    font_scale = 0.5  # 字体大小0.5
    thickness = 1  # 线宽1
    # cv.getTextSize动态获取文本,(fw, uph)是宽、高,dh是基线
    (fw, uph), dh = cv.getTextSize(label_txt, font, font_scale, thickness)
    (fw2, uph2), dh2 = cv.getTextSize(label_txt2, font, font_scale, thickness)
    cv.rectangle(canvas, (100, 80-uph-dh), (100+fw, 80), (255, 255, 255), -1, 8)
    cv.rectangle(canvas, (100, 100-uph2-dh2), (100+fw2, 100), (255, 255, 255), -1, 8)
    cv.putText(canvas, label_txt, (100, 80-dh), font, font_scale, (255, 0, 255), thickness)
    cv.putText(canvas, label_txt2, (100, 100-dh), font, font_scale, (255, 0, 255), thickness)
    cv.imshow("canvas", canvas)
    cv.waitKey(0)
    cv.destroyAllWindows()

动态显示文本示例:

计算机视觉OpenCv学习系列:第六部分、图像操作-2_第3张图片

第二节、多边形填充与绘制

1.多边形绘制函数

# 填充多边形
1.cv.fillPoly(img, pts, color[, lineType[, shift[, offset]]]) ->img
# 绘制多边形
2.cv.polylines(img, pts, isClosed, color[, thickness[, lineType[, shift]]] ) ->img
# pts表示一个或者多个点集
# color表示颜色
# thickness表示线宽,注意:必须大于0
# lineType 表示渲染方式

pts表示一个或多个点集

pts = []
pts.append((100, 100))
pts.append((200, 50))
pts.append((280, 100))
pts.append((290, 300))
pts.append((50, 300))
pts = np.asarray(pts, dtype=np.int32)
print(pts.shape)
# 要求:必须是CV_32S, 对应np.int32

2.绘制与填充


支持一次绘制多个图形

例如:红色边框是绘制、蓝色区域是填充

计算机视觉OpenCv学习系列:第六部分、图像操作-2_第4张图片

3.代码练习与测试


# 多边形绘制
def poly_demo():
    # 设置画布
    canvas = np.zeros((512, 512, 3), dtype=np.uint8)
    # pts = [(100, 100), (200, 50), (280, 100), (290, 300), (50, 300)]
    pts = []
    pts.append((100, 100))
    pts.append((200, 50))
    pts.append((280, 100))
    pts.append((290, 300))
    pts.append((50, 300))
    pts = np.array(pts, dtype=np.int32)
    print(pts.shape)

    pts2 = []
    pts2.append((300, 300))
    pts2.append((400, 250))
    pts2.append((500, 300))
    pts2.append((500, 500))
    pts2.append((250, 500))
    pts2 = np.array(pts2, dtype=np.int32)
    print(pts2.shape)

    # 同时绘制两个点集
    cv.polylines(canvas, [pts, pts2], True, (0, 0, 255), 2, 8)
    # 填充
    cv.fillPoly(canvas, [pts, pts2], (255, 0, 0), 8, 0)
    cv.imshow("poly-demo", canvas)
    cv.waitKey(0)
    cv.destroyAllWindows()

结果示例:

计算机视觉OpenCv学习系列:第六部分、图像操作-2_第5张图片

第三节、图像像素类型转换与归一化

1.归一化方法与支持


图像归一化就是让图像在不同情况下来回转换。

OpenCV中常用的归一化方法:

  • NORM_MINMAX
  • NORM_INF
  • NORM_L1
  • NORM_L2
  • 最常用 NORM_MINMAX
  • NORM_L1与NORM_L2范数
    • 下图中L1范数 = x / (∑ xi),例如0.1 = 2.0 / (2.0 + 8.0 + 10.0)
    • 下图中L2范数 = x / (∑ xi ^ 2) ^ 1/2 ,例如0.15 = 2.0 / (4.0 + 64.0 +100.0) ^ 1/2

计算机视觉OpenCv学习系列:第六部分、图像操作-2_第6张图片

2.归一化函数


1.cv.normalize(	src, dst[, alpha[, beta[, norm_type[, dtype[, mask]]]]]	) -> dst
# src表示输入图像, dst表示输出图像
# alpha, beta 默认是1, 0,是归一化的区间值
# norm_type默认是NORM_L2, 
# norm_type常用是NORM_MINMAX
2.数据转换
# Imread读入默认是uint8, 转换为float32
# 通过imshow显示之前,必须归一化到[0~1]之间。

计算机视觉OpenCv学习系列:第六部分、图像操作-2_第7张图片

3.代码练习与测试


图像像素NORM_MINMAX归一化:

# 图像像素类型转换与归一化
def norm_demo():
    image_uint8 = cv.imread(r"F:\python\opencv-4.x\samples\data\ml.png")
    cv.imshow("image_uint8", image_uint8)
    img_f32 = np.float32(image_uint8)
    cv.imshow("image_f32", img_f32)
    cv.normalize(img_f32, img_f32, 1, 0, cv2.NORM_MINMAX)
    cv.imshow("norm-img_f32", img_f32)
    cv.waitKey(0)
    cv.destroyAllWindows()

结果示例:当图片类型从uint8转换到f32之后,如果不适用归一化结果如中间所示只有一堆点,使用归一化之后结果如右图所示。

因为imshow只支持两种类型显示,一种是uint8(0, 255),另一种是f32(0, 1)。

计算机视觉OpenCv学习系列:第六部分、图像操作-2_第8张图片

滚动条显示四种归一化方法:

# 定义滚动条的注册响应
def trackbar_norm_callback(pos):
    print(pos)


# 用滚动条实现四种归一化方式
def norm_trackbar_demo():
    image_uint8 = cv.imread(r"F:\python\opencv-4.x\samples\data\ml.png")
    cv.namedWindow("norm-demo", cv.WINDOW_AUTOSIZE)
    # 注意使用cv.createTrackbar滚动条之前线要定义注册响应trackbar_norm_callback
    cv.createTrackbar("normtype", "norm-demo", 0, 3, trackbar_norm_callback)
    while True:
        dst = np.float32(image_uint8)
        pos = cv.getTrackbarPos("normtype", "norm-demo")
        if pos == 0:
            cv.normalize(dst, dst, 1, 0, cv.NORM_MINMAX)
        if pos == 1:
            cv.normalize(dst, dst, 1, 0, cv.NORM_L1)
        if pos == 2:
            cv.normalize(dst, dst, 1, 0, cv.NORM_L2)
        if pos == 3:
            cv.normalize(dst, dst, 1, 0, cv.NORM_INF)
        cv.imshow("norm-demo", dst)
        # 每过50ms就获取一个键值,默认键值为-1,ESC键值为27
        c = cv.waitKey(50)
        if c == 27:
            break
    cv.waitKey(0)
    cv.destroyAllWindows()

结果示例:

计算机视觉OpenCv学习系列:第六部分、图像操作-2_第9张图片

第四节、图像几何变换

1.图像几何变换矩阵


图像的变化使用几何变换矩阵实现的

所以图像几何变换最重要的就是几何变换矩阵M(2x3),前面四个参数是控制放缩,最后一列是平移

例如:矩形变圆形

  • 平移变换
    计算机视觉OpenCv学习系列:第六部分、图像操作-2_第10张图片

  • 放缩变换
    计算机视觉OpenCv学习系列:第六部分、图像操作-2_第11张图片

  • 旋转变换
    计算机视觉OpenCv学习系列:第六部分、图像操作-2_第12张图片

2.函数支持


# 仿射变换
1. cv.warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]	) --> dst
# src表示输入图像
# M 表示2x3变换矩阵
# dsize表示目标图像输出dst的大小
# 支持平移变换、放缩变换、旋转变换

输出dst形式如下所示:实现原坐标(x,y)到目标位置的变换

在这里插入图片描述

# 旋转矩阵获取
2. cv.getRotationMatrix2D
# Center表示旋转中心
# angle表示度数,>0表示逆时针旋转
# scale表示放缩尺度大小

# 翻转
3. cv.flip(src, flipCode[, dst]	) ->dst
# 特殊角度旋转
4. cv.rotate(src, rotateCode[, dst]	) -> dst
# src表示输入图像
# flipCode支持0水平、1垂直,-1对角线翻转,只表示翻转
# rotateCode只支持旋转90°,180°,270°,不支持任意角度旋转

3.代码练习与测试


# 图像几何旋转
def affine_demo():
    image = cv.imread(r"F:\python\opencv-4.x\samples\data\ml.png")
    h, w, c = image.shape
    # 获取中心位置
    cx = int(w/2)
    cy = int(h/2)
    cv.imshow("image", image)
    # 定义原图放缩0.7倍,上下均平移50的矩阵M
    M = np.zeros((2, 3), dtype=np.float32)
    M[0, 0] = .7
    M[1, 1] = .7
    M[0, 2] = 50
    M[1, 2] = 50
    print("M(2x3) = \n", M)
    dst = cv.warpAffine(image, M, (int(w*.7), int(h*.7)))
    cv.imshow("rescale-demo", dst)
    # 在指定路径写一个图片
    cv.imwrite(r"F:\python\opencv-4.x\result.png", dst)

    # 定义旋转,获取旋转矩阵degree>0,表示逆时针旋转,原点在左上角
    # (w/2, h/2)表示旋转中心,逆时针旋转45°,放缩1.0即不做放缩操作。
    M = cv.getRotationMatrix2D((w/2, h/2), 45.0, 1.0)
    dst = cv.warpAffine(image, M, (w, h))
    cv.imshow("rotate-demo", dst)

    # 图像翻转,0表示水平翻转
    dst = cv.flip(image, 0)
    cv.imshow("flip-demo", dst)

    # 图像特殊角度旋转,顺时针旋转90°
    dst = cv.rotate(image, cv.ROTATE_90_CLOCKWISE)
    cv.imshow("rotate-90-demo", dst)

    cv.waitKey(0)
    cv.destroyAllWindows()

结果示例:

计算机视觉OpenCv学习系列:第六部分、图像操作-2_第13张图片

学习参考

本系列所有OpenCv相关的代码示例和内容均来自博主学习的网站:opencv_course

你可能感兴趣的:(opencv,计算机视觉,学习)