C++ OpenCV實現抖音"藍線挑戰"特效
前言
本文將使用OpenCV C++ 實現抖音上的特效“藍線挑戰”。雖然看起來覺得很牛的樣子,但如果瞭解其中的原理就非常簡單瞭。本案例是我自己對於這個特效實現過程的理解,僅供參考。
算法原理可以分為三個流程:
1、將視頻(圖像)從(頂->底)或(左->右)逐行(列)掃描圖像。
2、將掃描完成的行(列)像素重新生成定格圖像。
3、使用原幀圖像像素填充未掃描到的像素。
接下來就具體來看看是如何實現的吧。
一、圖像掃描
首先第一步,拿到一個視頻(很多幀圖像)可以簡單的看成圖像處理。我們需要將圖像從頂到底逐行進行像素掃描,當然也可以從左到右逐列掃描,這要看你想要實現什麼樣的效果。在這裡,我實現的是從上到下逐行掃描。效果如圖所示。
二、生成定格圖像
所謂生成定格圖像就是將我們每掃描到的行像素重新進行繪制。
//從頂向下逐行掃描圖像 if (h < height) { h++; //將掃描到的圖像像素進行重新繪制,生成新圖像 for (int j = 0; j < width; j++) { for (int c = 0; c < 3; c++) { temp.at<Vec3b>(h, j)[c] = canvas.at<Vec3b>(h, j)[c]; } } //繪制掃描過程 line(canvas, Point(0, h), Point(width, h), Scalar(255, 255, 0), 2); }
如圖所示,這是使用上面代碼段實現的逐行掃描生成定格圖像。從效果上看,已經得到瞭我們想要的大致效果瞭。不過現在的問題是,經掃描到的行有像素填充,未掃描到的行還是漆黑一片。所以接下來我們需要做的就是將未掃描到的行用原圖進行填充。具體請看源碼註釋。
三、圖像混合
//將兩幅圖像進行線性混合 bool Linear_Blend(Mat src1, Mat src2, Mat& dst) { /* 參數說明: src1:生成的定格圖像。由於生成的定格圖像是從頂往下逐行掃描,故在掃描線下的像素為0 src2:原視頻幀圖像 dst:新生成的定格圖像。 算法原理:經掃描到的像素用src1進行填充,未掃描到的像素用src2進行填充,這樣就可以得到我們所要的效果瞭。 */ for (int i = 0; i < src1.rows; i++) { for (int j = 0; j < src1.cols; j++) { for (int c = 0; c < 3; c++) { if (src1.at<Vec3b>(i, j)[0] != 0) { dst.at<Vec3b>(i, j)[c] = src1.at<Vec3b>(i, j)[c]; } else { dst.at<Vec3b>(i, j)[c] = src2.at<Vec3b>(i, j)[c]; } } } } return true; }
四、效果顯示
如上圖所示,至此我們已經完成瞭案例所想要的效果。請參考源碼,註釋也比較詳細瞭。
五、源碼
#include<iostream> #include<opencv2/opencv.hpp> using namespace std; using namespace cv; /* 抖音特效:藍線挑戰 算法原理: 1、將視頻(圖像)從(頂->底)或(左->右)逐行(列)掃描圖像。 2、將掃描完成的行(列)像素重新生成定格圖像 3、使用原幀圖像像素填充未掃描到的像素 */ //將兩幅圖像進行線性混合 bool Linear_Blend(Mat src1, Mat src2, Mat& dst) { /* 參數說明: src1:生成的定格圖像。由於生成的定格圖像是從頂往下逐行掃描,故在掃描線下的像素為0 src2:原視頻幀圖像 dst:新生成的定格圖像。 算法原理:經掃描到的像素用src1進行填充,未掃描到的像素用src2進行填充,這樣就可以得到我們所要的效果瞭。 */ for (int i = 0; i < src1.rows; i++) { for (int j = 0; j < src1.cols; j++) { for (int c = 0; c < 3; c++) { if (src1.at<Vec3b>(i, j)[0] != 0) { dst.at<Vec3b>(i, j)[c] = src1.at<Vec3b>(i, j)[c]; } else { dst.at<Vec3b>(i, j)[c] = src2.at<Vec3b>(i, j)[c]; } } } } return true; } int main() { VideoCapture capture; capture.open("test.avi"); if (!capture.isOpened()) { cout << "can not open the camera!" << endl; system("pause"); return -1; } int width = capture.get(CAP_PROP_FRAME_WIDTH);//視頻幀寬 int height = capture.get(CAP_PROP_FRAME_HEIGHT);//視頻幀高 //保存視頻 VideoWriter writer; int fourcc = writer.fourcc('m', 'p', '4', 'v'); //視頻編碼 Size size(capture.get(CAP_PROP_FRAME_WIDTH), capture.get(CAP_PROP_FRAME_HEIGHT)); writer.open("result.avi", fourcc, 30, size, true); int h = 0;//定義變量,代表當前掃描高度 //用於生成定格照 Mat temp = Mat::zeros(Size(width, height), CV_8UC3); Mat frame; while (capture.read(frame)) { //將圖像拷貝一份,用於每幀更新 Mat canvas = frame.clone(); //從頂向下逐行掃描圖像 if (h < height) { h++; //將掃描到的圖像像素進行重新繪制,生成新圖像 for (int j = 0; j < width; j++) { for (int c = 0; c < 3; c++) { temp.at<Vec3b>(h, j)[c] = canvas.at<Vec3b>(h, j)[c]; } } //繪制掃描過程 line(canvas, Point(0, h), Point(width, h), Scalar(255, 255, 0), 2); } Mat result = Mat::zeros(frame.size(), frame.type());//藍線挑戰最終定格圖 Linear_Blend(temp, canvas, result); //將兩張圖像進行像素疊加 //writer.write(temp);//進行視頻保存 imshow("定格圖像", temp); imshow("原視頻幀", canvas); imshow("藍線挑戰", result); char key = waitKey(10); if (key == 27) break; } capture.release(); system("pause"); return 0; }
總結
本文使用OpenCV C++ 實現抖音特效“藍線挑戰”,關鍵步驟有以下幾點。
1、將圖像進行逐行掃描
2、將掃描到的像素逐行生成定格圖像
3、將定格圖像與原圖像進行像素疊加。
以上就是C++ OpenCV實現抖音"藍線挑戰"特效的詳細內容,更多關於C++ OpenCV藍線挑戰特效的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- python 基於opencv操作攝像頭
- C++ Opencv實現錄制九宮格視頻
- 基於opencv實現車道線檢測
- 如何使用Python的OpenCV庫處理圖像和視頻
- Python+OpenCV讀寫視頻的方法詳解