精华内容
下载资源
问答
  • opencv动画

    2017-03-24 16:03:49
    动画opencv动画制作
  • OpenCV动画编程教程

    2014-02-20 15:48:19
    OpenCV是一个基于(开源)发行的跨平台计算机视觉库,可以运行在Linux、Windows和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了...
  • 基于opencv动画操作

    千次阅读 2016-01-06 21:04:07
    opencv一些图形绘制操作

    opencv动画操作

    大家应该熟悉opencv是一个图像处理或者说是计算机视觉库,但是在opencv中有这么一个头文件highgui.h。这个头文件中封装了很多类似windowsGUI的操作,甚至有时候调用起来逻辑更加清晰。

    首先这个头文件中封装了一些简单的图形绘画操作:

    cvCircle( CvArr* img, CvPoint center, int radius, CvScalar color, int thickness=1, int line_type=8, int shift=0 );


    cvLine( CvArr* img, CvPoint pt1, CvPoint pt2, CvScalar color, int thickness=1, int line_type=8, int shift=0 );


    cvRectangle( CvArr* img, CvPoint pt1, CvPoint pt2, CvScalar color,int thickness=1, int line_type=8, int shift=0 ;CvSize min_size=cvSize(0,0);CvSize max=cvSize(0,0));


    看名字就能看出来,就是一些按照定点画出圆,线,矩形。


    那么我们怎么才能用这些基本操作画出复杂的动画UI呢?


    我们知道,动画就是一帧一帧渐变的图像,我们是不是可以这么想,如果我每一帧图像都变一点,最后把所有帧都连起来就是个动画呢。


    opencv提供这一基础的函数就是cvWaitkey;


    char cvWaitkey(int);

    这个函数将返回一个char型的值,作为瞬间响应按钮,我们可以利用这个值对动画的动作进行控制。

    而括号里的int值就是等待时间,也就是帧和帧之间的间隔时间,单位是ms;

    如果int值为0则表示一直等待char类型按键的响应;


    那么首先,我们先画两个可以一直变大的圆锥形;

    圆锥其实就是由无数个圆组成的,让圆在特定的直线上慢慢变大就可以形成一个圆锥。


    	IplImage *img0;
    	img0=cvLoadImage("test0.jpg");
    
    		cvNamedWindow("My Window");//建立窗口
    		int a=0;
    		int b=0;
    		int t=0;
    		int k=1;
    
    	while(true){
    	
    		cvCircle(img0,cvPoint(b,a),k,CV_RGB(255,0,255),3);//画圆 
    		cvShowImage("My Window", img0);
    		cvWaitKey(20); //20ms一帧图像
    		a+=2;
    		b+=1;	
    		k++;//改变控制圆大小
    
    	}
    	

    这就可以动态显示一个类似圆锥的图像动画。


    接下来我们就可以玩一些高难度的操作。

    opencv中没有定义清除函数,这让非常多的动画方案都难以实现,比如说我要显示下雨,但是画了线以后线就留在了那里,没有消失,会越变越多,不能控制。

    那么opencv又可以怎么样去显示可清除动态呢?

    这里的核心算法就是cvCloneImage。

    我把显示的原图作为克隆源,每显示一张就销毁一张,每次画的都是新的图像,这样就可以成功的绕开所谓的清除函数。


    还是以原来的那个圆锥举例,现在就可以显示一个慢慢放大的圆形了;

    	IplImage *img0;
    	img0=cvLoadImage("test0.jpg");
    	IplImage *img1=cvCreateImage(cvGetSize(img0),img0->depth,img0->nChannels);
    	
    
    	cvNamedWindow("My Window");
    	int a=0;
    	int b=0;
    	int t=0;
    	int k=1;
    
    	while(true){
    	
    		img1=cvCloneImage(img0);
    	
    		cvCircle(img1,cvPoint(b,a),k,CV_RGB(255,0,255),3);
    		cvShowImage("My Window", img1);
    		cvWaitKey(20); 
    		a+=2;
    		b+=1;
    		k++;
    
    	}


    下面是效果图


    最后我们要做一个炫酷的,那就是放大镜。

    我们知道放大镜可以跟着鼠标移动,并显示鼠标周围的图像然后放大,这个操作就有些难度了。


    我们首先要熟悉鼠标操作,我的另外一篇博客中有写opencv鼠标操作,

    这样利于鼠标我们就可以完成这件事了。


    首先读入一张图像。

    在鼠标函数中复制这张图像,以免在操作时候画在圆图像上。

    IplImage *imgx=cvLoadImage("test.jpg");
    IplImage *imgcopyx=cvCreateImage(cvGetSize(imgx),imgx->depth,imgx->nChannels);
    
    void onMouse(int Event,int x,int y,int flags,void* param )//====================================响应鼠标点击事件
    {
    	imgcopyx=cvCloneImage(imgx);
    }


    设置鼠标回调函数,并且实时获取xy坐标。


    我们再设置一个区域作为放大区域,这个区域是围绕着xy坐标的;

    cvSetImageROI(imgcopyx , cvRect(x-100,y-100,200,200));


    这个区域设置必须加上条件,否则就会让区域超出图像导致程序崩溃;

    if (x>=100&&y>=100&&x<=imgcopyx->width-100&&y<=imgcopyx->height-100&&edgeshow);
    
    


    最后我们再将已经设置好区域的图像拷贝到新的,长宽一致的图像中,画上一些标准线就行了;

    cvCircle(rectimg,cvPoint(rectimg->width/2,rectimg->height/2),10,CV_RGB(255,255,255),2);
    cvLine(rectimg,cvPoint(0,rectimg->height/2),cvPoint(rectimg->width,rectimg->height/2),CV_RGB(255,0,0),1);
    cvLine(rectimg,cvPoint(rectimg->width/2,0),cvPoint(rectimg->width/2,imgx->height),CV_RGB(255,0,0),1);


    整个程序大致是这样

    IplImage *imgx=cvLoadImage("test.jpg");
    IplImage *imgcopyx=cvCreateImage(cvGetSize(imgx),imgx->depth,imgx->nChannels);
    
    void onMouse(int Event,int x,int y,int flags,void* param )//====================================响应鼠标点击事件
    {
    	/*printf("( %d, %d) ",x,y);
    	printf("The Event is : %d ",Event);
    	printf("The flags is : %d ",flags);
    	printf("The param is : %d\n",param);*/
    	imgcopyx=cvCloneImage(imgx);
    	IplImage *rectimg=cvCreateImage(cvSize(200,200),imgcopyx->depth,imgcopyx->nChannels);
    	if (x>=100&&y>=100&&x<=imgcopyx->width-100&&y<=imgcopyx->height-100&&edgeshow)
    	{
    		cvSetImageROI(imgcopyx , cvRect(x-100,y-100,200,200));
    		
    		cvCopy(imgcopyx,rectimg); 
    		cvCircle(rectimg,cvPoint(rectimg->width/2,rectimg->height/2),10,CV_RGB(255,255,255),2);
    		cvLine(rectimg,cvPoint(0,rectimg->height/2),cvPoint(rectimg->width,rectimg->height/2),CV_RGB(255,0,0),1);
    		cvLine(rectimg,cvPoint(rectimg->width/2,0),cvPoint(rectimg->width/2,imgx->height),CV_RGB(255,0,0),1);
    
    		cvNamedWindow("辅助操作窗口",0);
    		cvResizeWindow("辅助操作窗口",rectimg->width*1.5,rectimg->height*1.5);
    		cvMoveWindow("辅助操作窗口",x+100,y-300);
    		//cvMoveWindow("辅助操作窗口",imgcopyx->width+200,imgcopyx->height-300);
    		cvShowImage("辅助操作窗口",rectimg);
    		
    	}
    	cvReleaseImage(&rectimg);
    	cvReleaseImage(&imgcopyx);
    }

    效果有些像某些输入法的放大功能,如下:

     

    炫酷吧,其实opencv里面的GUI操作并不少,就看怎么样去结合,去实现自己想要的算法。

    很多动画很多事情分解开来其实都很简单。


    reference:

    http://baike.baidu.com/





    
    展开全文
  • 主要为大家详细介绍了opencv利用鼠标滑动画出多彩的形状,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • QT+OpenCV照片动画风格转换

    千次阅读 2018-02-12 08:56:54
    OpenCV将摄像头采集到的图片转换成动画风格,加上了QT界面。这个小实验并不复杂,后面直接贴代码。 代码 在QT creator中建的工程,只上部分比较重要的代码了,其他都是一样的。 mainWindow.h:定义了一些槽...

    前言

    用OpenCV将摄像头采集到的图片转换成动画风格,加上了QT界面。这个小实验并不复杂,后面直接贴代码。

    代码

    在QT creator中建的工程,只上部分比较重要的代码了,其他都是一样的。
    mainWindow.h:定义了一些槽函数以及中间变量。

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include <QTimer>
    #include <QDebug>
    #include <opencv2/opencv.hpp>
    #include <iostream>
    
    namespace Ui {
    class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
    
        QImage cvMat2QImage(const cv::Mat & mat);
        void cartoonize(cv::Mat & src, cv::Mat & dst);
        void cartoonize_v2(cv::Mat & src, cv::Mat & dst);
    
    private slots:
        void on_pushButton_clicked();
    
        void on_pushButton_2_clicked();
    
        void on_pushButton_3_clicked();
    
        void readFrame();
    
    private:
        Ui::MainWindow *ui;
    
        bool cartoonize_flag;
    
        QImage dst_image;
        QTimer *timer;
    
        cv::VideoCapture camera;
        cv::Mat frame;
        cv::Mat cartoon_image;
    };
    
    #endif // MAINWINDOW_H

    mainWindow.cpp:具体定义了那些函数。

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        this->timer = new QTimer(this);
        this->cartoonize_flag = false;
        this->connect(this->timer, SIGNAL(timeout()), this, SLOT(readFrame()));
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    //从摄像头读取一帧图像
    void MainWindow::readFrame()
    {
        this->camera >> this->frame;
    
        if(frame.empty())
        {
            std::cerr<<"ERROR: Couldn't grab a camera frame."<<  std::endl;
            exit(1);
        }
    
        if(this->cartoonize_flag)
        {
            //this->frame.copyTo(this->cartoon_image);
            cartoonize(this->frame, this->cartoon_image);
            cv::cvtColor(this->cartoon_image, this->cartoon_image, cv::COLOR_BGR2RGB);
        }
        else
        {
            cv::cvtColor(this->frame, this->cartoon_image, cv::COLOR_BGR2RGB);
            //this->frame.copyTo(this->cartoon_image);
        }
    
        // the image must be converted into RGB, but not the default BGR in OpenCV
        this->dst_image = cvMat2QImage(this->cartoon_image);
    
        //在GraphicView中显示图像
        QGraphicsScene *scene = new QGraphicsScene;
        scene->addPixmap(QPixmap::fromImage(this->dst_image));
        ui->graphicsView->setScene(scene);
        ui->graphicsView->show();
    }
    
    //打开摄像头,映射到按键1的槽函数
    void MainWindow::on_pushButton_clicked()
    {
        //Open Camera
        this->camera.open(0);
        if(!this->camera.isOpened())
        {
            std::cerr << "Could not access the camera or video!" << std::endl;
            exit(1);
        }
        this->camera.set(cv::CAP_PROP_FRAME_WIDTH, 640);
        this->camera.set(cv::CAP_PROP_FRAME_HEIGHT, 480);
    
        this->timer->start(33);
    }
    
    //是否进行卡通化转换标志,映射到按键2的槽函数
    void MainWindow::on_pushButton_2_clicked()
    {
        //Cartoonizing
        this->cartoonize_flag = !this->cartoonize_flag;
    }
    
    //关闭摄像头,映射到按键3的槽函数
    void MainWindow::on_pushButton_3_clicked()
    {
        //Close Camera
        this->timer->stop();
        this->camera.release();
        exit(1);
    }
    
    //OpenCV中Mat类型转换为Qt中的QImage类型
    QImage MainWindow::cvMat2QImage(const cv::Mat & mat)
    {
        //if(!mat.empty())
        //{
            //bgr->rgb
            //cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB);
        //}
        switch(mat.type())
        {
        case CV_8UC1:
        {
            QImage img(mat.cols, mat.rows, QImage::Format_Indexed8);
            img.setColorCount(255);
            for(int i=0;i<256;i++)
            {
                img.setColor(i, qRgb(i,i,i));
            }
            uchar * pSrc = mat.data;
            for(int row=0;row<mat.rows;row++)
            {
                uchar *pDest = img.scanLine(row);
                memcpy(pDest, pSrc, mat.cols);
                pSrc += mat.step;
            }
            return img;
        }
        case CV_8UC3:
        {
            const uchar * pSrc = (const uchar *)mat.data;
            QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
            return image.copy();
        }
        case CV_8UC4:
        {
            const uchar * pSrc = (const uchar *)mat.data;
            QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32);
            return image.copy();
        }
        default:
        {
            qDebug() << "ERROR: Mat could not be converted to QImage.";
            return QImage();
        }
        }
    }
    
    //卡通化处理
    void MainWindow::cartoonize(cv::Mat & src, cv::Mat & dst)
    {
        cv::Mat gray;
        cv::cvtColor(src, gray, cv::COLOR_BGR2GRAY);//转成灰度图
        const int MEDIAN_BLUR_FILTER_SIZE = 7;
        cv::medianBlur(gray, gray, MEDIAN_BLUR_FILTER_SIZE);//中值滤波
    
        cv::Mat edges;
        const int LAPLACIAN_FILTER_SIZE = 5;
        cv::Laplacian(gray, edges, CV_8U, LAPLACIAN_FILTER_SIZE);//边缘检测,也可用canny检测或是其他算法
    
        cv::Mat mask;
        const int EDGES_THRESHOLD = 65;
        cv::threshold(edges, mask, EDGES_THRESHOLD, 255, cv::THRESH_BINARY_INV);//二值化,生成边缘掩码,注意是cv::THRESH_BINARY_INV
        mask.copyTo(dst);
    
        //为了保证处理速度,将图像大小压缩一倍
        cv::Size srcSize = src.size();
        cv::Size newSize;
        newSize.width = srcSize.width / 2;
        newSize.height = srcSize.height / 2;
        cv::Mat newImg = cv::Mat(newSize, CV_8UC3);
        cv::resize(src, newImg, newSize, 0, 0, cv::INTER_LINEAR);
    
        //做两次双边滤波
        cv::Mat tmp = cv::Mat(newSize, CV_8UC3);
        int repetitions = 3;
        for(int i=0;i<repetitions;i++)
        {
            int ksize = 9;
            double sigmaColor = 11;
            double sigmaSpace = 5;
            cv::bilateralFilter(newImg, tmp, ksize, sigmaColor, sigmaSpace);
            cv::bilateralFilter(tmp, newImg, ksize, sigmaColor, sigmaSpace);
        }
    
        cv::Mat resImg;
        cv::resize(newImg, resImg, srcSize, 0, 0, cv::INTER_LINEAR);//调整回原来的大小
        dst.setTo(0);
        resImg.copyTo(dst, mask);
    }
    

    运行结果:
    这里写图片描述

    这里写图片描述

    这里写图片描述

    参考链接:
    https://zhuanlan.zhihu.com/p/24416498
    http://blog.csdn.net/liyuanbhu/article/details/46662115
    http://blog.csdn.net/AP1005834/article/details/51263012

    展开全文
  • 主要介绍了C++&&Opencv实现控制台字符动画的方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
  • 在这篇博客中,我们将学习如何使用Python,OpenCV,dlib和ImageMagick工具箱创建动画GIF。 使用OpenCV构建一个模因生成器!我们以多种实用方式利用了计算机视觉和深度学习,包括:人脸检测、面部标志预测、提取...

    在这篇博客中,我们将学习如何使用Python,OpenCV,dlib和ImageMagick工具箱创建动画GIF。 然后,您将结合所有这些技术,使用OpenCV构建一个模因生成器(眼镜👓和文字Deal with it)

    效果图:
    在这里插入图片描述
    首先,讨论该项目的先决条件和依赖项,包括如何正确配置开发环境。
    然后,将审查OpenCV GIF创建的项目/目录结构。
    最后,了解项目结构后,我们将审查(1)我们的配置文件,以及(2)我们的Python脚本,该脚本负责使用OpenCV创建GIF。

    使用OpenCV构建模因生成器,可以教会我们实践中使用的许多有价值的技术,包括:

    1. 如何执行基于深度学习的面部检测
    2. 如何使用dlib库进行面部标志检测并提取眼睛区域
    3. 如何拍摄这两个区域并计算眼睛之间的旋转角度
    4. 最后,如何使用OpenCV生成动画GIF(在ImageMagick的帮助下)

    1. 先决条件和依赖项

    1. OpenCV,dlib

    OpenCV将用于面部检测和基本图像处理。dlib用于面部标志检测,使我们能够找到眼镜并降下;
    OpenCV安装,通过pip:

    pip install opencv
    

    dlib安装可参考: https://editor.csdn.net/md/?articleId=105896031

    2. ImageMagick

    ImageMagick是基于跨平台命令行的工具,提供了很多图像处理功能。

    • 可通过一个命令将PNG/JPG转换为PDF
    • 可将多张图片转换成PDF幻灯片
    • 可绘制多边形,直线和其他形状
    • 可在单个命令中进行批处理颜色调整或者整个图像数据集的空间尺寸调整
    • 可通过一组输入图像生成GIF图像。

    要在Ubuntu(或Raspbian)上安装ImageMagick,只需使用apt:

    sudo apt-get install imagemagick
    

    macOS上安装ImageMagick,则可以使用HomeBrew:

    brew install imagemagick
    

    windows10上安装ImageMagick,可以使用:
    下载:ImageMagick-7.0.10-13-Q16-x64-static.exe http://www.imagemagick.org/script/download.php
    安装完cmd窗口测试:

    magick logo: logo.gif
    magick identify logo.gif
    magick logo.gif win:
    

    能看到图片就是正常滴;

    3. imutils

    方便图像处理的便捷方法类包。安装:

    pip install imutils
    

    2. 项目结构

    在这里插入图片描述

    3. 生成GIF

    # USAGE
    # python create_gif.py --config config.json --image images/girl.jpg --output girl_out.gif
    
    # 导入必要的包
    from imutils import face_utils
    from imutils import paths
    import numpy as np
    import argparse
    import imutils
    import shutil
    import json
    import dlib
    import cv2
    import sys
    import os
    
    
    # 叠加前景图像(fg  )在背景图像(bg  )在位置坐标(它们是(x,y)坐标),从而可以通过前景蒙版fgMask实现Alpha透明。
    def overlay_image(bg, fg, fgMask, coords):
        # 获取前景图片的空间维度(宽度 和 高度),然后计算前景图片将被放置的坐标元组
        (sH, sW) = fg.shape[:2]
        (x, y) = coords
    
        # 叠加层应该和输入图像具有相同的宽度和高度,前景完全空白,通过数组切片将其添加到叠加层中
        overlay = np.zeros(bg.shape, dtype="uint8")
        overlay[y:y + sH, x:x + sW] = fg
    
        # alpha通道(控制给定的区域 放置在哪里以及多大的透明度) 也需要与输入图像具有与相同的宽度和高度,但是仅包括前景图片的蒙版层
        alpha = np.zeros(bg.shape[:2], dtype="uint8")
        alpha[y:y + sH, x:x + sW] = fgMask
        alpha = np.dstack([alpha] * 3)
    
        # 执行Alpha混合以合并前景,背景和alpha通道
        output = alpha_blend(overlay, bg, alpha)
    
        # 返回输出图像
        return output
    
    
    def alpha_blend(fg, bg, alpha):
        # 转换前景图,背景图,alpha层 由8位的int 到float,确保alpha层透明度在[0,1]之间
        fg = fg.astype("float")
        bg = bg.astype("float")
        alpha = alpha.astype("float") / 255
    
        # 执行 alpha 混合
        fg = cv2.multiply(alpha, fg)
        bg = cv2.multiply(1 - alpha, bg)
    
        # 叠加前景,背景图,以获取最终输出
        output = cv2.add(fg, bg)
    
        # 返回输出图像
        return output.astype("uint8")
    
    
    def create_gif(inputPath, outputPath, delay, finalDelay, loop):
        # 获取输入路径的所有图像
        imagePaths = sorted(list(paths.list_images(inputPath)))
    
        # 移除list中的最后一个路径
        lastPath = imagePaths[-1]
        imagePaths = imagePaths[:-1]
    
        # 构建  ImageMagick命令行以生成输出的GIF,给一个足够大的时间延迟以得到最终输出动画
        cmd = "magick -delay {} {} -delay {} {} -loop {} {}".format(
            delay, " ".join(imagePaths), finalDelay, lastPath, loop,
            outputPath)
        os.system(cmd)
    
    
    # 构建命令行参数并解析
    # --config: JSON配置文件的路径
    # --image: 输入图像的路径
    # --output: 输出gif的路径
    ap = argparse.ArgumentParser()
    ap.add_argument("-c", "--config", required=True,
                    help="path to configuration file")
    ap.add_argument("-i", "--image", required=True,
                    help="path to input image")
    ap.add_argument("-o", "--output", required=True,
                    help="path to output GIF")
    args = vars(ap.parse_args())
    
    # 加载config文件
    # 读取太阳镜图像,太阳镜蒙版图像
    config = json.loads(open(args["config"]).read())
    sg = cv2.imread(config["sunglasses"])
    sgMask = cv2.imread(config["sunglasses_mask"])
    
    # 如果以前运行的脚本有任何残留,我们从磁盘上删除临时目录,然后重新创建一个空的临时目录。临时文件夹将在GIF中保存每个单独的帧
    shutil.rmtree(config["temp_dir"], ignore_errors=True)
    os.makedirs(config["temp_dir"])
    
    # cv2.dnn.readNetFromCaffe: 加载OpenCV的面部检测器,dnn模块在OpenCV3.3 之后支持
    # 加载dlib的面部标志检测器(允许我们定位面部的结构:如眼睛、眉毛、鼻子、嘴、下颌)
    print("[INFO] loading models...")
    detector = cv2.dnn.readNetFromCaffe(config["face_detector_prototxt"],
                                        config["face_detector_weights"])
    predictor = dlib.shape_predictor(config["landmark_predictor"])
    
    # 检测 脸 及 眼睛位置
    # 加载输入图像并从图像构建输入Blob
    image = cv2.imread(args["image"])
    image = imutils.resize(image, width=500)
    (H, W) = image.shape[:2]
    blob = cv2.dnn.blobFromImage(cv2.resize(image, (300, 300)), 1.0,
                                 (300, 300), (104.0, 177.0, 123.0))
    
    # 通过面部检测神经网络传递Blob并获得检测结果
    print("[INFO] computing object detections...")
    detector.setInput(blob)
    detections = detector.forward()
    
    # 假设只有一张人脸,我们将发现并给其戴上太阳镜
    # 确定找到具有最大概率的面部
    i = np.argmax(detections[0, 0, :, 2])
    confidence = detections[0, 0, i, 2]
    
    # 过滤掉置信度比较低的检测
    if confidence < config["min_confidence"]:
        print("[INFO] no reliable faces found")
        sys.exit(0)
    
    # 提取脸部 并计算面部标志
    # 计算脸部的坐标边界框
    box = detections[0, 0, i, 3:7] * np.array([W, H, W, H])
    (startX, startY, endX, endY) = box.astype("int")
    
    # 构建dlib矩形对象,并应用面部标志定位
    rect = dlib.rectangle(int(startX), int(startY), int(endX), int(endY))
    shape = predictor(image, rect)
    shape = face_utils.shape_to_np(shape)
    
    # 提取左眼、右眼的下标索引
    # 找到相对的左眼、右眼的坐标
    (lStart, lEnd) = face_utils.FACIAL_LANDMARKS_IDXS["left_eye"]
    (rStart, rEnd) = face_utils.FACIAL_LANDMARKS_IDXS["right_eye"]
    leftEyePts = shape[lStart:lEnd]
    rightEyePts = shape[rStart:rEnd]
    
    # 给定眼睛的坐标,我们可以计算太阳镜的放置位置和放置方式:
    # 计算每只眼睛的中心,然后计算眼睛质心之间的角度,就像执行面部对齐一样。
    leftEyeCenter = leftEyePts.mean(axis=0).astype("int")
    rightEyeCenter = rightEyePts.mean(axis=0).astype("int")
    
    # 计算眼睛中心的角度
    dY = rightEyeCenter[1] - leftEyeCenter[1]
    dX = rightEyeCenter[0] - leftEyeCenter[0]
    angle = np.degrees(np.arctan2(dY, dX)) - 180
    print('angle: ', angle)
    
    # 根据计算的角度旋转我们的眼镜,确保眼镜👓和头是对齐的 【使用rotate_bound 而不是rotate,确保仿射变换后,OpenCV不会裁剪掉超出边界的图像部分。】
    sg = imutils.rotate_bound(sg, angle)
    
    # 眼镜👓不应该占据整个脸的宽度,最理想的是仅仅覆盖了眼睛,这里我们将使用一个合适的宽度——脸宽度的90%作为眼镜的宽度
    sgW = int((endX - startX) * 0.9)
    sg = imutils.resize(sg, width=sgW)
    
    # 应用于太阳镜本身的相同操作也需要应用于面罩。首先,由于蒙版始终是二进制的,因此我们需要将蒙版转换为灰度并将其二进制化。然后我们像对太阳镜处理相同的步骤,旋转蒙版并调整其大小
    # 请注意,在调整遮罩大小时使用了最近邻插值。这是因为我们的遮罩应该只有两个值(0和255)。其他插值方法在审美上可能更美观,但实际上会对我们的面罩有害。
    sgMask = cv2.cvtColor(sgMask, cv2.COLOR_BGR2GRAY)
    sgMask = cv2.threshold(sgMask, 0, 255, cv2.THRESH_BINARY)[1]
    sgMask = imutils.rotate_bound(sgMask, angle)
    sgMask = imutils.resize(sgMask, width=sgW, inter=cv2.INTER_NEAREST)
    
    # 创建GIF帧
    # 太阳镜将会从上边以相同的速度用N步滑向期待的眼睛的位置 开始创建每一帧的效果
    # 我们的太阳镜将从图像顶部掉落,每帧依次显示太阳镜逐渐靠近脸部,直到遮住眼睛为止。
    # 使用我们的JSON配置变量“ steps” (步骤数),利用NumPy的linspace,在0和右眼的y值之间生成均匀间隔的y值,将太阳镜分别放在每个镜架上
    # np.linspace主要用来创建等差数列
    steps = np.linspace(0, rightEyeCenter[1], config["steps"],
                        dtype="int")
    # 循环遍历步数
    for (i, y) in enumerate(steps):
        # 计算太阳镜的平移
        # 确保太阳镜能覆盖每只眼睛,而不仅仅是到达眼中心的位置,根据经验确定了百分比值:x位移*0.25 y位移*0.35,并确保没有负值
        shiftX = int(sg.shape[1] * 0.25)
        shiftY = int(sg.shape[0] * 0.35)
        y = max(0, y - shiftY)
    
        # 利用overlay_image生成图像的一帧
        output = overlay_image(image, sg, sgMask,
                               (rightEyeCenter[0] - shiftX, y))
    
        # 我们的最终输出帧是一种特殊情况,因为它是“ DEAL WITH IT”文本,我们将通过另一种屏蔽操作在框架上绘制该文本:
        # 如果是最后一步移动了,需要把“DEAL WITH IT”文本添加到帧的底部
        # 选择使用图片是因为OpenCV的字体渲染能力非常有限,而且想在文本上添加阴影和边框,这也是OpenCV无法做到的。
        if i == len(steps) - 1:
            # 加载“DEAL WITH IT” 和其蒙版图像 确保我们做了与太阳镜相同的处理(灰度图并且阈值化了该蒙版)
            dwi = cv2.imread(config["deal_with_it"])
            dwiMask = cv2.imread(config["deal_with_it_mask"])
            dwiMask = cv2.cvtColor(dwiMask, cv2.COLOR_BGR2GRAY)
            dwiMask = cv2.threshold(dwiMask, 0, 255,
                                    cv2.THRESH_BINARY)[1]
    
            # resize图像和蒙版为 输出图像宽度的 80%
            oW = int(W * 0.8)
            dwi = imutils.resize(dwi, width=oW)
            dwiMask = imutils.resize(dwiMask, width=oW,
                                     inter=cv2.INTER_NEAREST)
    
            # 计算文本在输出图像的位置并且添加文本到图像
            oX = int(W * 0.1)
            oY = int(H * 0.8)
            output = overlay_image(output, dwi, dwiMask, (oX, oY))
    
        # 输出图像存储在临时文件夹中
        p = os.path.sep.join([config["temp_dir"], "{}.jpg".format(
            str(i).zfill(8))])
        cv2.imwrite(p, output)
    
    # 所有图像的帧已写入临时文件夹中,制作GIF图
    print("[INFO] creating GIF...")
    # 调用 create_gif 函数来生成GIF动画文件,create_gif 函数是将参数传递给ImageMagick的convert的包装器工具以执行其命令行。
    create_gif(config["temp_dir"], args["output"], config["delay"],
               config["final_delay"], config["loop"])
    
    cv2.waitKey(0)
    # 清理删除临时文件夹
    print("[INFO] cleaning up...")
    shutil.rmtree(config["temp_dir"], ignore_errors=True)
    

    参考: https://www.pyimagesearch.com/2018/11/05/creating-gifs-with-opencv/210393818/

    展开全文
  • 教程简介:本教程使用 OpenCV 处理图片视频,将视频转为字符画序列,再在终端中播放字符动画。除了 OpenCV 的操作,本教程还会了解光标定位转义编码的使用。本项目教程由FrostSigh发布在实验楼,完整教程及在线练习...

    教程简介:本教程使用 OpenCV 处理图片视频,将视频转为字符画序列,再在终端中播放字符动画。除了 OpenCV 的操作,本教程还会了解光标定位转义编码的使用。

    本项目教程由FrostSigh发布在实验楼,完整教程及在线练习地址:Python3 & OpenCV 视频转字符动画

    一、项目简介

    在介绍如何用 Python3 & OpenCV 将视频转成字符动画之前,先简单的介绍一下 OpenCV 吧,毕竟可能很多小伙伴不太了解:

    百度百科:OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux、Windows和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。

    1.1. 知识点OpenCV 编译

    使用 OpenCV 处理图片、视频

    图片转字符画原理

    守护线程

    光标定位转义编码

    1.2. 效果展示

    接着来看看效果展示,很可爱又很酷炫:(动画截图)

    播放停止后的效果,注意终端中并无残留的动画字符:

    二、项目原理

    大家应该都明白视频其实可以看作一系列图片组成的,因此视频转字符动画最基本的便是图片转字符画,这一部分内容也在 Python 图片转字符画 课程中有讲过。

    在这里简单的说一下图片转字符画的原理:首先将图片转为灰度图,每个像素都只有亮度信息(用 0~255 表示)。然后我们构建一个有限字符集合,其中的每一个字符都与一段亮度范围对应,我们便可以根据此对应关系以及像素的亮度信息把每一个像素用对应的字符表示,这样字符画就形成了。

    字符动画要能播放才有意义。最最简单粗暴的,用文本编辑器打开字符动画文本文件,然后狂按 PageDown 键就能播放。然而这真的太简单太粗暴了,一点都不优雅。

    我们还是在终端里面播放字符动画,只需要一帧一帧输出就能达到动画的效果了,然而这却有一个很大的弊端:播放时,你会发现终端右边的滚动条会越来越小(如果有的话);播放完毕后,在终端中往上翻页,全是之前输出的字符画,播放前的命令历史全部被挤占掉了。在本实验后面提供了这个问题的解决办法。

    三、实验环境及OpenCV的编译安装

    在线练习环境:

    实验楼为本项目提供了在线环境。本课程的实验中使用了 OpenCV 3.1,因此我们需要编译安装它。首先我们需要处理一个问题:当前实验楼的环境中 python3 命令使用的 python 版本为 3.5,我们需要将 python3 命令使用的 python 版本切换为 3.4。

    $ sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.4 70 --slave /usr/bin/python3m python3m /usr/bin/python3.4m

    然后安装一些依赖的包:

    $ sudo apt-get update

    $ sudo apt-get install python3-dev

    $ sudo pip3 install numpy

    $ sudo apt-get install cmake libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev

    现在可以开始编译 OpenCV 3.1 了,下面是在实验楼环境中编译 OpenCV 3.1 所需的命令,其他环境中的编译请参考官网。

    $ wget https://github.com/Itseez/opencv/archive/3.1.0.zip

    $ unzip 3.1.0.zip && cd opencv-3.1.0/

    $ mkdir build && cd build

    $ cmake -D CMAKE_BUILD_TYPE=Release \

    -D CMAKE_INSTALL_PREFIX=/usr/local \

    PYTHON3_EXECUTABLE=/usr/bin/python3 \

    PYTHON_INCLUDE_DIR=/usr/include/python3.4 \

    PYTHON_LIBRARY=/usr/lib/x86_64-linux-gnu/libpython3.4m.so \

    PYTHON3_NUMPY_INCLUDE_DIRS=/usr/local/lib/python3.4/dist-packages/numpy/core/include ..

    $ make -j4

    不想自己编译的同学请下载编译好的二进制文件,然后解压并进入 opencv-3.1.0/build 目录。

    本项目的完整代码、详细步骤及demo,可以在实验楼查看并在线完成:Python3 & OpenCV 视频转字符动画

    更多Python经典项目:Python全部 - 课程

    展开全文
  • 基于Unity3D的人脸动态贴纸的实现,利用openCv人脸识别库,在人脸的指定位置定位显示动态的动画效果,有3类的动画实现,帧动画、骨骼动画、粒子系统动画
  • Python3 & OpenCV 视频转字符动画

    千次阅读 2017-02-17 15:51:24
    Python3 & OpenCV 视频转字符动画 一、实验简介 1.1. 知识点 OpenCV 编译使用 OpenCV 处理图片、视频图片转字符画原理守护线程光标定位转义编码 1.2. 效果展示 (由于是在线环境,流畅度是不及本地...
  • OpenCV 实现视频转字符动画 1 知识点 OpenCV 编译 使用 OpenCV 处理图片、视频 图片转字符画原理 守护线程 光标定位转义编码 2 实验环境 python 3.5 opencv-python-3.4.1 pyprind-2.11.2 实验步骤 环境搭建 关于...
  • Opencv实现控制台字符动画原理概述获取图像中某像素点的颜色图片载入变量将图片转化为灰度图获取图片某像素点的颜色将控制台光标移动到指定坐标总结 原理概述 首先利用opencv获取到图片中特定像素点的颜色 根据颜色...
  • opencv实现图片动画效果

    千次阅读 2016-11-05 17:43:42
    #include <opencv2\core\utility.hpp> #include <opencv2\imgproc.hpp> #include <opencv2\highgui.hpp> #include #include #include using namespace std; using namespace cv; Mat img = ...
  • GoFlip 将视频转换成类似自己的版本的Flip-Book。 gocv库用于所有处理。 将视频保存在./data文件夹中,然后运行以下命令。 go run *.go <NameOfVideo> 原始影片 产生的视频
  • 今天没有继续学习新知识点,画出了一个随鼠标画出的图形,知识点全都是之前学的,话不多说,先上图: ...opencv2/opencv.hpp> using namespace cv; using namespace std; #define WINDOW_NAME "【窗口程序】" ..
  • 原理概述首先利用opencv获取到图片中特定像素点的颜色根据颜色所处的范围选择不同的字符再在控制台的特定位置打印即可重点就是获取像素点的颜色获取图像中某像素点的颜色图片载入变量opencv中可使用Mat类型来储存...
  • OpenCV

    2017-08-30 11:14:56
    https://github.com/ming1016/study/wiki/OpenCV ...OpenCV 戴铭 edited this page May 4, 2015 · 2 revisions  Pages 62 HomeAuto LayoutBlockCameraCFRunLoopCocoapodsCollect
  • gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) #使用opencv转化成灰度图 gray = cv2.resize(gray,(show_width,show_heigth))#resize灰度图 text = "" for pixel_line in gray: for pixel in pixel_line: #...
  • OpenCV3+python3实现视频转字符动画

    千次阅读 2018-08-04 16:32:25
    1、实验环境  Anaconda python 3.5  Opencv 3  pyprind 2  Ubuntu 16.04 2、环境安装 2.1下载 Anaconda python 3.5 linux版 wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/Anaconda3...
  • 这里 α按步长0.001递增。 import cv2 import numpy as np import time img1=cv2.imread('stitch.jpg') img2=cv2.imread('pikachu.jpg') # 当进行图像融合时,被叠加的两张图片的大小、类型(高度/宽度/通道数)必须...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,557
精华内容 2,222
关键字:

opencv动画