树莓派OpenCV系列教程6:10行代码添加国旗

来自丢石头百科


在学完前面较为枯燥的概念后,接下来,是时候展现真正的技术了。由于OpenCV既是机器视觉库,也是图像处理库,给头像添加国旗,那自然是小菜一碟,如果用Python写的话,只要10行左右。

1 思路分析

好比把大象装进冰箱要几步一样,为头像添加上国旗也是如此,先不讲通过什么语言实现,毕竟语言只是工具,OK,如果那,那为头像添加上国旗则需要以下几个步骤:

  • Step1:读取头像和国旗图案。
  • Step2:把国旗叠加到头像上。
  • Step3:把叠加后的图片保存。


把大象放进冰箱只要这么几步,但是具体把国旗叠加到头像上,需要考虑的一体细节:

  • 国旗必须缩放到合适大小,才能放到头像上。
  • 国旗缩放后不能变形。 因此:

    就把国旗的宽度缩放至头像宽度的1/4,然后高度也按照同样的比例进行缩放。

  • 核心问题已经解决了,剩下来就是工具自身实现的问题,在OpenCV中,读写图像,缩放图像,图像合成,图像显示,是比较基本的操作,现在,就开始驾驭工具,把大象放入冰箱,先从Python开始讲起:

    2 Python实现

    <syntaxhighlight lang="python">
    # -*- coding: utf8 -*-
    import cv2
    
    # Step1:读取头像和国旗图像。
    img_head = cv2.imread('head.jpg')
    img_flag = cv2.imread('flag.jpg')
    
    # Step2:把国旗叠加到头像上。
    # Step2.1:获取头像和国旗宽度
    w_head, h_head = img_head.shape[:2]
    w_flag, h_flag = img_flag.shape[:2]
    # Step2.2:根据宽度计算缩放比例
    scale = w_head / w_flag / 4
    # Step2.3:根据缩放比例缩放国旗
    img_flag = cv2.resize(img_flag, (0, 0), fx=scale, fy=scale)
    # Step2.4:获取缩放后国旗的新尺寸
    w_flag, h_flag = img_flag.shape[:2]
    # Step2.5:根据缩放后的尺寸叠加国旗到头像右下角
    for c in range(0, 3):
        img_head[w_head - w_flag:, h_head - h_flag:, c] = img_flag[:, :, c]
    
    # Step3:保存叠加后的图像
    cv2.imwrite('new_head.jpg', img_head)
    

    </syntaxhighlight>

    程序执行效果如下图所示: 20191028175608.png

    注释有说明步骤相关的思路及其实现。

    3 C++实现

    接下来,来看看C++执行相关的代码

    <syntaxhighlight lang="python">
    #include<iostream>
    #include<opencv2/opencv.hpp>
    #include<opencv2/highgui/highgui.hpp>
    #include<opencv2/imgproc/imgproc.hpp>
    
    using namespace std;
    using namespace cv;
    
    int main()
    {
        //Step1:读取头像和国旗图像。
        Mat img_head = imread("head.jpg");
        Mat img_flag = imread("flag.jpg");
        Mat img_flag_resized;
    
        //Step2:把国旗叠加到头像上。
        //Step2.1:获取头像和国旗宽度
        int w_head = img_head.cols;
        int h_head = img_head.rows;
        int w_flag = img_flag.cols;
        int h_flag = img_flag.rows;
        //Step2.2:根据宽度计算缩放比例
        double scale = (double)w_head/w_flag/4;
        //Step2.3:根据缩放比例缩放国旗    
        resize(img_flag,img_flag_resized,Size(),scale,scale,INTER_NEAREST);
        //Step2.4:获取缩放后国旗的新尺寸
        w_flag = img_flag_resized.cols;
        h_flag = img_flag_resized.rows;
        //Step2.5:根据缩放后的尺寸叠加国旗到头像右下角
        Mat imageROI=img_head(Rect(w_head-w_flag,h_head-h_flag,w_flag,h_flag));
        img_flag_resized.copyTo(imageROI);
    
        //Step3:保存叠加后的图像
        imwrite("new_head.jpg",img_head);
        return 0;
    }
    

    </syntaxhighlight>

    其CmakeList.txt为:

    <syntaxhighlight lang="python">
    cmake_minimum_required(VERSION 3.0)
    project(07_National_Flag)
    find_package(OpenCV REQUIRED)
    add_executable(07_National_Flag main.cpp)
    target_link_libraries(07_National_Flag ${OpenCV_LIBS})
    

    </syntaxhighlight>

    执行结果图下图所示: 20191028194113.png

    其执行效果同Python。