Opencv将处理后的视频保存出现的问题

1,108 阅读3分钟

问题描述:
代码运行过程中,imshow出来的每帧的效果图是正确的,但是按照网上的方法保存下来却是0kb,打开不了。
参考的网上的一些方法,均是失败的,具体原因我也不清楚:
1、例如我这样设置,会报这样的错:
错误
2、后来经过查找,这种表示方法更换成:

int outCompressCodec = CAP_OPENCV_MJPEG;// 设置要保存视频的格式。

这回不报错了,但是产生的视频文件仍然是为0kb;
3、
设置为和输入视频一样的格式:

int outCompressCodec = capture.get(CAP_PROP_FOURCC);

不报错,但是产生的视频文件仍然是为0kb;
4、还有不知道是那种操作,导致这样的提示:
程序运行的过程中面板上弹出的错误是:这个应该是涉及到编码与解码的库,但老实说不需要下载相关库,自带的也可以实现我所需要的功能的。

[ INFO:0] VIDEOIO: Enabled backends(5, sorted by priority): FFMPEG(1000); MSMF(990); DSHOW(980); CV_IMAGES(970); CV_MJPEG(960)

Failed to load OpenH264 library: openh264-1.8.0-win64.dll
        Please check environment and/or download library: https://github.com/cisco/openh264/releases

[libopenh264 @ 00000232d8d77f00] Incorrect library version loaded
Could not open codec 'libopenh264': Unspecified error

5、最后发现原来按照CAP_OPENCV_MJPEG设置的话,输出的视频必须为MP4格式,我还傻逼呼呼地用avi格式,最终结果很好!!

这是我写的代码:(将avi输出为MP4)

#include <opencv2/opencv.hpp>
#include "opencv2/features2d.hpp"
#include<opencv2/highgui.hpp>
#include <iostream>
#include "windows.h"
#include <stdio.h>
#include <time.h>
#include <math.h>  
#include "My_ImageProssing_base.h"
#define WINDOW_NAME "【程序窗口】"			
using namespace cv;
using namespace std;
//RNG g_rng(12345);


//失败

//对视频进行动漫化一般需要四个步骤
//1、边缘检测
//2、将边缘检测得到的边缘 以黑色的形式贴在原来的画上。
//3、对贴了边缘的图进行双边滤波,双边滤波可以较好的滤波的同时保留边缘。
//4、修改图像的颜色的饱和度,本文采用的是将RGB转化为HSV空间,然后调整S分量。

//*--------------------------【全局变量声明】-------------------------------------*/
int g_nThresholdValue = 71;	//canny参数值
int g_nkernelValue = 21;	//双边滤波核大小
int g_nS = 248;	//
Mat g_srcImage, g_grayImage,g_cannyImage,g_dstImage;

void H_mul_k(Mat* srcImage, Mat* dstImage, float k)
{
	int height = (*srcImage).rows;
	int width = (*srcImage).cols;
	for (int j = 0; j < height; j++)
	{
		for (int i = 0; i < width; i++)
		{
			int zhi = (*srcImage).at<uchar>(j, i) * k;
			if (zhi >= 255) zhi = 255;
			else if (zhi <= 0) zhi = 0;
			else zhi = zhi;
			(*dstImage).at<uchar>(j, i) = zhi;
		}
	}
}
int main(int argc, char* argv[])
{
	Point pt1, pt2;
	Mat g_srcImage;
	cv::VideoCapture capture("D:\\opencv_picture_test\\毛概期中作业\\路上风景.avi");//关联读入视频文件
	if (!capture.isOpened()) {
		std::cout << "fail to load video";
		return 1;
	}
	/*获取视频fps*/
	double rate = capture.get(CAP_PROP_FPS);
	/*获取视频帧的尺寸*/
	int width = capture.get(CAP_PROP_FRAME_WIDTH);
	int height = capture.get(CAP_PROP_FRAME_HEIGHT);
	// 获取当前视频的编码格式,输出的视频要和输入视频编码相同才可以保存。
	//int outCompressCodec = capture.get(CAP_PROP_FOURCC);
	int outCompressCodec = CAP_OPENCV_MJPEG;// 设置要保存视频的格式。
	cout << outCompressCodec << endl;
	/*根据打开视频的参数初始化输出视频格式*/
	//D:\\opencv_picture_test\\毛概期中作业\\re_video.avi
	cv::VideoWriter w_cap("D:\\opencv_picture_test\\毛概期中作业\\re_video.mp4", outCompressCodec, rate, cv::Size(width, height),true);
	/*自定义输出视频的尺寸,需要将读取的视频帧尺寸进行变换,下文使用的resize函数完成*/
	//cv::VideoWriter w_cap("re_video.avi", outCompressCodec, rate, cv::Size(width,height));
	
	/*循环读取视频的帧*/
	while (capture.read(g_srcImage)) {
		/****************************************************************************************************************************/
		/*对读取的视频帧进行处理*/
		g_grayImage.create(g_srcImage.size(), g_srcImage.type());		//创建一个同大小类型的矩阵
		cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);
		//imshow("【原图的灰度图】", g_grayImage);
		//进行均值滤波操作
		blur(g_grayImage, g_grayImage, Size(3, 3));
		//【4】创建滑动条来控制阈值
		//【1】运行canny算子
		Canny(g_grayImage, g_cannyImage, g_nThresholdValue, g_nThresholdValue / 3, 3);
		cv::Mat g_canny3Image(g_srcImage.rows, g_srcImage.cols, CV_8UC3, cv::Scalar(0, 0, 0));
		//【2】贴图
		//将canny图反转(将边缘变为黑色)
		Mat change_g_cannyImage;
		//change_g_cannyImage = g_cannyImage < 100;		//非边缘转化为255,边缘转化为0;非边缘会在之后的处理会变为透明,而边缘则会保持原有的数据0
		change_g_cannyImage = 255 - g_cannyImage;
		//将单通道转化为三通道
		cvtColor(change_g_cannyImage, g_canny3Image, COLOR_GRAY2BGR);
		//image.copyTo(imageROI,mask), 作用是把mask和image重叠以后把mask中像素值为0(black)的点对应的image中的点变为透明,而保留其他点。
		Mat bianyuan_dst;
		g_srcImage.copyTo(bianyuan_dst, g_canny3Image);
		//【3】双边滤波
		Mat lvbo_dst;
		bilateralFilter(bianyuan_dst, lvbo_dst, g_nkernelValue, g_nkernelValue * 2, g_nkernelValue / 2);
		//【4】修改图像的颜色的饱和度
		Mat hsv_image, hsv_dst;
		cvtColor(lvbo_dst, hsv_image, COLOR_BGR2HSV);
		vector<Mat> channels;
		split(hsv_image, channels);
		Mat S_Mat;
		float k = g_nS * 1.0f / 100;
		channels.at(1).copyTo(S_Mat);
		cv::Mat S_dst(S_Mat.rows, S_Mat.cols, CV_8UC1, cv::Scalar(0));
		//S_dst = S_Mat * k;
		H_mul_k(&S_Mat, &S_dst, k);
		//将修改后的S与原来的H,V进行merge
		channels[1] = S_dst.clone();	//深复制
		merge(channels, hsv_dst);
		//将修改后的HSV转为RGB图
		Mat RGB_dst;
		cvtColor(hsv_dst, RGB_dst, COLOR_HSV2BGR);
		/****************************************************************************************************************************/

		/*保存处理后的帧为视频*/
		w_cap.write(RGB_dst);
		//这里我们不展示
		//imshow("src", RGB_dst);
		if (waitKey(10)=='q')
		{
			break;
		}
	}
	capture.release();
	cout << "处理好了" << endl;
	return 0;
}

参考链接们:

opencv视频读取与帧处理后保存为视频的方法
利用opencv加快视频播放速度,并保存avi视频文件
opencv4.0.0里面CV_FOURCC找不到标识符
opencv VideoWriter保存视频失败原因
opencv视频保存
OpenCV视频写入详解_Python,视频保存0kb问题
解决c++ - openh264 - bEnableFrameSkip=0, bitrate can’t be controlled
常见的视频格式以及视频编解码标准(附带OpenCV实现视频的读取与保存)

十分感谢上面的链接!!!