zoukankan      html  css  js  c++  java
  • 第五篇 学习OpenCV之视频处理

    // 作者:GongchuangSu ( http://blog.csdn.net/gongchuangsu )
    // 时间:2015.07.26
    // 说明:从视频文件中读入数据,将读入数据转换为灰度图,对图像做Canny边缘检测。
    //       将上面三个步骤实现显示在一个图像中,并在图像的三个不同部分写上合适的
    //       标签,同时在这幅图像中任何地方点击鼠标,将当前图像的坐标显示于点击鼠标处。
    // 注意:当R = G = B时为灰度色。
    
    #include "cv.h"
    #include "highgui.h"
    #include <iostream>
    using namespace std;
    //#pragma comment(linker, "/subsystem:"windows" /entry:"mainCRTStartup"")
    int col = 0;
    int row = 0;
    char *str = (char *)malloc(30*sizeof(char *));
    // 定义 Canny 边缘检测函数
    IplImage* doCanny(
        IplImage* in,
        int lowThresh,
        int highThresh,
        int aperture
        ){
            if( in->nChannels != 1)  // Canny只能处理灰度图片
                return(0);
            IplImage* out = cvCreateImage(
                cvGetSize( in ),
                in->depth,
                in->nChannels
                );
            cvCanny( in, out, lowThresh, highThresh, aperture );
            return( out );
    };
    // 定义鼠标回调函数
    void my_mouse_callback( int event, int x, int y, int flags, void* param){
        if( event == CV_EVENT_LBUTTONDOWN){
            col = x;
            row = y;
        }
    }
    int main()
    {
        // 定义 Canny 边缘检测的阈值
        int thresh = 30;
        // 定义字体相关属性
        CvFont font;
        cvInitFont( &font, CV_FONT_HERSHEY_PLAIN, 1, 1, 0, 1, 8);
        const char *AviName="MV.mp4";
        const char *WindowsTitle = "Merge";
        cvNamedWindow( WindowsTitle, 1);
        CvCapture *capture=cvCreateFileCapture(AviName);
        // 取得视频文件的大小并输出 
        CvSize size = cvSize(
            (int)cvGetCaptureProperty( capture, CV_CAP_PROP_FRAME_WIDTH),
            (int)cvGetCaptureProperty( capture, CV_CAP_PROP_FRAME_HEIGHT)
            );
        // 创建图像 
        IplImage *src = cvCreateImage( size, IPL_DEPTH_8U, 3);
        IplImage *dst_gray = cvCreateImage( size, IPL_DEPTH_8U, 1);
        IplImage *dst_canny = cvCreateImage( size, IPL_DEPTH_8U, 1);
        IplImage *dst_merge = cvCreateImage( cvSize( size.width*3, size.height), IPL_DEPTH_8U, 3);
        // 创建三个图像头,分别指向图像 dst_merge 的开始处、1/3处、2/3处
        IplImage *src_header = cvCreateImageHeader( size, IPL_DEPTH_8U, 3);
        src_header->origin = dst_merge->origin;
        src_header->widthStep = dst_merge->widthStep;
        src_header->imageData = dst_merge->imageData;
        IplImage *dst_gray_header = cvCreateImageHeader( size, IPL_DEPTH_8U, 3);
        dst_gray_header->origin = dst_merge->origin;
        dst_gray_header->widthStep = dst_merge->widthStep;
        dst_gray_header->imageData = dst_merge->imageData + dst_merge->widthStep/3;
        IplImage *dst_canny_header = cvCreateImageHeader( size, IPL_DEPTH_8U, 3);
        dst_canny_header->origin = dst_merge->origin;
        dst_canny_header->widthStep = dst_merge->widthStep;
        dst_canny_header->imageData = dst_merge->imageData + dst_merge->widthStep*2/3;
        // 创建图像头 dst_gray_header 的单通道 r ,g ,b 图像
        IplImage *dst_gray_header_r = cvCreateImage( cvGetSize(dst_gray_header), dst_gray_header->depth, 1);
        IplImage *dst_gray_header_g = cvCreateImage( cvGetSize(dst_gray_header), dst_gray_header->depth, 1);
        IplImage *dst_gray_header_b = cvCreateImage( cvGetSize(dst_gray_header), dst_gray_header->depth, 1);
        // 创建图像头 dst_canny_header 的单通道 r ,g ,b 图像
        IplImage *dst_canny_header_r = cvCreateImage( cvGetSize(dst_canny_header), dst_canny_header->depth, 1);
        IplImage *dst_canny_header_g = cvCreateImage( cvGetSize(dst_canny_header), dst_canny_header->depth, 1);
        IplImage *dst_canny_header_b = cvCreateImage( cvGetSize(dst_canny_header), dst_canny_header->depth, 1);
        // 读取视频并转换
        while( (src = cvQueryFrame(capture)) != NULL )
        {
            // 将原始图像拷贝给指向合并图像开始处的图像头
            cvCopy( src, src_header);
            // 将原始图像转换为灰度图像
            cvConvertImage( src, dst_gray);
            // 将灰度图像头分割成红、绿、蓝三个单通道图像,并将灰度图像拷贝给三个单通道图像,然后再将三个单通道
            // 合并,以使灰度图像头显示的是灰度图像。
            cvZero(dst_gray_header);
            cvSplit( dst_gray_header, dst_gray_header_r, dst_gray_header_g, dst_gray_header_b, 0);
            cvCopy( dst_gray, dst_gray_header_r);
            cvCopy( dst_gray, dst_gray_header_g);
            cvCopy( dst_gray, dst_gray_header_b);
            cvMerge( dst_gray_header_r, dst_gray_header_g, dst_gray_header_b, 0, dst_gray_header);
            // 将灰度图像进行 Canny 边缘检测处理
            dst_canny = doCanny( dst_gray, thresh, 3*thresh, 3);
            cvZero(dst_canny_header);
            cvSplit( dst_canny_header, dst_canny_header_r, dst_canny_header_g, dst_canny_header_b, 0);
            cvCopy( dst_canny, dst_canny_header_r);
            cvCopy( dst_canny, dst_canny_header_g);
            cvCopy( dst_canny, dst_canny_header_b);
            cvMerge( dst_canny_header_r, dst_canny_header_g, dst_canny_header_b, 0, dst_canny_header);
            // 在合并图像的三个不同处显示相应的文字
            cvPutText( dst_merge, "Color", cvPoint(315,25), &font, cvScalar( 255, 255, 255));
            cvPutText( dst_merge, "Gray", cvPoint(315*3,25), &font, cvScalar( 255, 255, 255));
            cvPutText( dst_merge, "Canny", cvPoint(315*5,25), &font, cvScalar( 255, 255, 255));
            cvShowImage( WindowsTitle, dst_merge);
            // 设置鼠标回调函数
            cvSetMouseCallback(
                WindowsTitle,
                my_mouse_callback,
                (void *)dst_merge
                );
            // 输出坐标值
            cout<<"( x, y) = "<<"( "<<col<<", "<<row<<")"<<endl;
            memset( str, 0, 30);
            // 将格式化的数据写入字符串缓冲区
            sprintf( str, "( %d, %d)",col,row);
            // 将字符串显示在相应的图像位置
            cvPutText( dst_merge, str, cvPoint(col,row), &font, cvScalar( 0, 0, 255)); 
            cvShowImage(WindowsTitle,dst_merge);
            // 等待按键触发
            char c = cvWaitKey(33);
            if( c == 27)
                break;
        }
        // 释放资源,销毁窗口
        cvReleaseCapture(&capture);
        cvReleaseImage(&dst_merge);
        cvReleaseImage(&src);
        cvReleaseImage(&dst_gray);
        cvReleaseImage(&dst_canny);
        cvReleaseImageHeader(&src_header);
        cvReleaseImageHeader(&dst_gray_header);
        cvReleaseImageHeader(&dst_canny_header);
        cvReleaseImage(&dst_gray_header_r);
        cvReleaseImage(&dst_gray_header_g);
        cvReleaseImage(&dst_gray_header_b);
        cvReleaseImage(&dst_canny_header_r);
        cvReleaseImage(&dst_canny_header_g);
        cvReleaseImage(&dst_canny_header_b);
        cvDestroyAllWindows();
        return(0);
    }

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

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    Codeforces1070 2018-2019 ICPC, NEERC, Southern Subregional Contest (Online Mirror, ACM-ICPC Rules, Teams Preferred)总结
    Codeforces 633H Fibonacci-ish II【线段树】
    一些Fibonacci数列的神奇性质【数学】
    Codeforces 620E New Year Tree【线段树傻逼题】
    Codeforces 828C String Reconstruction【并查集巧妙运用】
    Codeforces 559C Gerald and Giant Chess【组合数学】【DP】
    Codeforces 311B Cats Transport【斜率优化DP】
    BZOJ2933 [Poi1999]地图【区间DP】
    BZOJ3688 折线统计【树状数组优化DP】
    BZOJ2131 免费的馅饼【线段树优化DP】
  • 原文地址:https://www.cnblogs.com/gongchuangsu/p/4850214.html
Copyright © 2011-2022 走看看