• 9月10日OpenCV学习笔记——Mask、彩色直方图、人脸检测



    前言

    本文为9月10日OpenCV学习笔记——Mask、彩色直方图、人脸检测,分为五个章节:

    • Mask;
    • 彩色直方图;
    • 画出基本图形;
    • 图片上显示文本;
    • 人脸检测。

    一、Mask

    提取感兴趣的区域。

    import cv2 as cv
    import matplotlib.pyplot as plt
    import numpy as np
    
    # 方法:显示图片
    def show_image(image, title, pos):
        img_RGB = image[:, :, ::-1] # BGR to RGB
        plt.title(title)
        plt.subplot(2, 2, pos)
        plt.imshow(img_RGB)
    
    # 方法:显示灰度直方图
    def show_histogram(hist, title, pos, color):
        plt.subplot(2, 2, pos)
        plt.title(title)
        plt.xlim([0, 256])
        plt.plot(hist, color=color)
    
    # 主函数
    def main():
        # 创建一个画布
        plt.figure(figsize=(12, 7))
        plt.suptitle("Gray Image and Histogram with mask", fontsize=14, fontweight="bold")
    
        # 加载图片并转成灰度,计算直方图、显示
        img_gray = cv.imread("images/vonmises.png", cv.COLOR_BGR2GRAY)
        img_gray_hist = cv.calcHist([img_gray], [0], None, [256], [0, 256]) # 计算直方图
        show_image(img_gray, "image gray", 1)
        show_histogram(img_gray_hist, "image gray histogram", 2, "m")
    
        # 创建 mask,计算位图,直方图
        mask = np.zeros(img_gray.shape[:2], np.uint8)
        mask[130:500, 300:700] = 255 # 获取 mask,并赋予颜色
    
        img_mask_hist = cv.calcHist([img_gray], [0], mask, [256], [0, 256]) # 计算 mask 直方图
    
        # 通过与运算计算带有 mask 的灰度图片
        mask_img = cv.bitwise_and(img_gray, img_gray, mask=mask)
    
        # 显示带有 mask 的图片和直方图
        show_image(mask_img, "gray image with mask", 3)
        show_histogram(img_mask_hist, "histogram with masked gray image", 4, "m")
    
        plt.show()
    
    if __name__ == '__main__':
        main()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    1


    二、彩色直方图

    import cv2 as cv
    import matplotlib.pyplot as plt
    import numpy as np
    
    # 方法:显示图片
    def show_image(image, title, pos):
        plt.subplot(3, 2, pos)
        plt.title(title)
        image_RGB = image[:, :, ::-1] # BGR to RGB
        plt.imshow(image_RGB)
        plt.axis("off")
    
    # 方法:显示彩色直方图
    def show_histogram(hist, title, pos, color):
        plt.subplot(3, 2, pos)
        plt.title(title)
        plt.xlim([0, 256])
        for h, c in zip(hist, color):  # color: ('b', 'g', 'r')
            plt.plot(h, color=c)
    
    # 方法:计算直方图
    def calc_color_hist(image):
        # b, g, r
        hist = []
        color = ('b', 'g', 'r')
        # print(tuple(enumerate(color)))
        for i, _ in enumerate(color):  # list(enumerate) ==> [(0, 'b'), (1, 'g'), (2, 'r')]
            hist.append(cv.calcHist([image], [i], None, [256], [0, 256]))
    
        return hist
    
    # 主函数
    def main():
        # 创建画布
        plt.figure(figsize=(12, 8))
        plt.suptitle("Color Histogram", fontsize=14, fontweight="bold")
    
        # 读取原图片
        img = cv.imread("./images/vonmises.png")
    
        # 计算直方图
        img_hist = calc_color_hist(img)
    
        # 显示图片和直方图
        show_image(img, "RGB Image", 1)
        show_histogram(img_hist, "RGB Image Hist", 2, ('b', 'g', 'r'))
    
        # 原始图片中的每个像素增加 50个像素值
        M = np.ones(img.shape, dtype="uint8") * 50
    
        added_image = cv.add(img, M)
        added_image_hist = calc_color_hist(added_image)
        show_image(added_image, "Added Image", 3)
        show_histogram(added_image_hist, "Added Image Hist", 4, ('b', 'g', 'r'))
    
        # 原始图片中的每个像素减少 50个像素值
        subtracted_img = cv.subtract(img, M)
        subtracted_img_hist = calc_color_hist(subtracted_img)
        show_histogram(subtracted_img, "Subtracted Image", 5, ('b', 'g', 'r'))
        show_histogram(subtracted_img_hist, "Subtracted Image Hist", 6, ('b', 'g', 'r'))
    
        plt.show()
    
    if __name__ == '__main__':
        main()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65

    2


    三、画出基本图形

    import cv2 as cv
    import numpy as np
    import matplotlib.pyplot as plt
    
    # 定义颜色(字典形式)
    colors = {'blue': (255, 0, 0),
               'green': (0, 255, 0),
               'red': (0, 0, 255),
               'yellow': (0, 255, 255),
               'magenta': (255, 0, 255),
               'cyan': (255, 255, 0),
               'white': (255, 255, 255),
               'black': (0, 0, 0),
               'gray': (125, 125, 125),
               'rand': np.random.randint(0, high=256, size=(3, )).tolist(),
               'dark_gray': (50, 50, 50),
               'light_gray': (220, 220, 220)}
    
    # 方法:显示图片
    def show_image(image, title):
        img_RGB = image[:, :, ::-1]  # BGR to RGB
        plt.title(title)
        plt.imshow(img_RGB)
        plt.show()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    1. 画直线, cv2.line( ):
    # 创建画布
    canvas = np.zeros((400, 400, 3), np.uint8)  # 默认背景是黑色
    canvas[:] = colors["white"]
    show_image(canvas, "Background")
    
    # 画直线 cv.line()
    cv.line(canvas, (0, 0), (400, 400), colors['green'], 5)
    cv.line(canvas, (0, 400), (400, 0), colors['black'], 5)
    show_image(canvas, "cv.line()")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3

    1. 画长方形,cv2.rectangle( )
    cv.rectangle(canvas, (10, 20), (70, 120), colors['green'], 3)
    cv.rectangle(canvas, (150, 50), (200, 300), colors['blue'], -1)  # -1: 填充
    show_image(canvas, "cv.rectangle()")
    
    • 1
    • 2
    • 3

    4

    1. 画圆型,cv2.circle( )
    cv.circle(canvas, (200, 200), 150, colors["black"], 3)
    cv.circle(canvas, (200, 200), 50, colors["green"], -1)
    show_image(canvas, "cv.circle()")
    
    • 1
    • 2
    • 3

    5

    1. 画折线,cv2.polylines( )
    pts = np.array([[250, 5], [220, 80], [280, 80]], np.int32)
    pts = pts.reshape((-1, 1, 2))
    cv.polylines(canvas, [pts], True, colors["green"], 3)
    
    pts2 = np.array([[150, 200], [90, 130], [280, 180]], np.int32)
    pts2 = pts2.reshape([-1, 1, 2])
    cv.polylines(canvas, [pts2], False, colors['black'], 5)
    show_image(canvas, "cv.polylines")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    6


    四、图片上显示文本

    import cv2 as cv
    import numpy as np
    import matplotlib.pyplot as plt
    
    # 定义颜色(字典形式)
    colors = {'blue': (255, 0, 0),
               'green': (0, 255, 0),
               'red': (0, 0, 255),
               'yellow': (0, 255, 255),
               'magenta': (255, 0, 255),
               'cyan': (255, 255, 0),
               'white': (255, 255, 255),
               'black': (0, 0, 0),
               'gray': (125, 125, 125),
               'rand': np.random.randint(0, high=256, size=(3, )).tolist(),
               'dark_gray': (50, 50, 50),
               'light_gray': (220, 220, 220)}
    
    # 方法:显示图片
    def show_image(image, title):
        img_RGB = image[:, :, ::-1]  # BGR to RGB
        plt.title(title)
        plt.imshow(img_RGB)
        plt.show()
    
    # 创建画布
    canvas = np.zeros((400, 400, 3), np.uint8) # 默认背景是黑色
    canvas.fill(255) # canvas[:] = colors[""]
    
    # 往画布上输入文本
    cv.putText(canvas, "Hello World", (50, 50), cv.FONT_HERSHEY_SIMPLEX, 0.9, colors["red"], cv.LINE_4)
    
    show_image(canvas, "Canvas")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    7


    五、人脸检测

    • 目标: 确定人脸位置,画出矩形框。

    • 原理: 使用 Haar-like 特征做检测:特征值为白色矩形像素和减去黑色矩形像素和。

      • Integral Image:积分图加速特征计算;
      • AdaBoost : 选择关键特征,进行人脸和非人脸分类;
      • Cascade : 级联,弱分类器成为强分类器。
      • 四个级联分类器(针对人脸的正面):
        1. haarcascade_frontalface_alt.xml (FA1);
        2. haarcascade_frontalface_alt2.xml (FA2);
        3. haarcascade_frontalface_alt_tree.xml (FAT);
        4. haarcascade_frontalface_default.xml (FD)。
          8
    import cv2 as cv
    
    # 方法:绘制图片中检测到的人脸
    def plot_rectangle(image, faces):
        # 拿到检测到的人脸数据(4个值):坐标(x, y), width, height
        for (x, y, w, h) in faces:
            cv.rectangle(image, (x, y), (x+w, y+h), (255, 0, 0), 3)
        return image
    
    # 主函数
    def main():
    
        # 读取摄像头
        capture = cv.VideoCapture(0)
    
        # 通过 cv.CascadeClassifier() 加载级联分类器
        faces_alt2 = cv.CascadeClassifier("haarcascade_frontalface_alt2.xml")
    
        # 判断摄像头是否正常工作
        if capture.isOpened() is False:
            print("Camera Error !")
    
        while capture.isOpened():
            # 获取每一帧
            ret, frame = capture.read()
            print(ret)
            if ret:
                gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
    
                # 使用该分类器对图像中的人脸进行检测
                faces_alt2_detect = faces_alt2.detectMultiScale(gray)
    
                # 绘制图片中检测到的人脸
                faces_alt2_result = plot_rectangle(frame.copy(), faces_alt2_detect)
    
                cv.imshow("Face Detection", faces_alt2_result)
    
                if cv.waitKey(20) & 0xFF == ord("q"):
                    break
            else:
                break
    
        capture.release()
        cv.destroyAllWindows()
    
    if __name__ == '__main__':
        main()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    9


  • 相关阅读:
    Java(常用类01)
    leetcode Top100 (5) 盛最多水的容器
    【Selenium】Selenium4 Grid
    LeetCode-1408-数组中的字符串匹配
    Wasabi Technologies领导团队新增日本和澳大利亚业务高管,以支持整个亚太区对热云存储的需求
    (亲测有效)推荐2024最新的免费漫画软件app,无广告,聚合全网资源!
    Java设计模式面试题及答案(持续更新。。。)
    (云HIS)云医院管理系统源码 SaaS模式 B/S架构 基于云计算技术
    C++学习过程中的一些值得注意的小点(1)
    Windows 环境搭建 PostgreSQL 物理复制高可用架构数据库服务
  • 原文地址:https://blog.csdn.net/Ashen_0nee/article/details/126784678