問題描述:
代碼運行過程中,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.dllPlease 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.avicv::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;非邊緣會在之后的處理會變為透明,而邊緣則會保持原有的數據0change_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進行mergechannels[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實現視頻的讀取與保存)
十分感謝上面的鏈接!!!