問題描述:
代碼運行過程中,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實現視頻的讀取與保存)
十分感謝上面的鏈接!!!