wordpress网站导入数据库,深圳最新政策消息,绵阳网站建设软件有哪些,网站模板大全原理
算法原理可以分为三个流程#xff1a;
1、将视频#xff08;图像#xff09;从#xff08;顶-底#xff09;或#xff08;左-右#xff09;逐行#xff08;列#xff09;扫描图像。
2、将扫描完成的行#xff08;列#xff09;像素重新生成定格图像…原理
算法原理可以分为三个流程
1、将视频图像从顶-底或左-右逐行列扫描图像。
2、将扫描完成的行列像素重新生成定格图像。
3、使用原帧图像像素填充未扫描到的像素。
图像扫描
首先第一步拿到一个视频很多帧图像可以简单的看成图像处理。我们需要将图像从顶到底逐行进行像素扫描当然也可以从左到右逐列扫描这要看你想要实现什么样的效果。在这里我实现的是从上到下逐行扫描。效果如图所示。 生成定格图像
所谓生成定格图像就是将我们每扫描到的行像素重新进行绘制。 //从顶向下逐行扫描图像if (h height){h;//将扫描到的图像像素进行重新绘制生成新图像for (int j 0; j width; j){for (int c 0; c 3; c){temp.atVec3b(h, j)[c] canvas.atVec3b(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生成的定格图像。由于生成的定格图像是从顶往下逐行扫描故在扫描线下的像素为0src2原视频帧图像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.atVec3b(i, j)[0] ! 0){dst.atVec3b(i, j)[c] src1.atVec3b(i, j)[c];}else{dst.atVec3b(i, j)[c] src2.atVec3b(i, j)[c];}}}}return true;
} 效果 源码
#includeiostream
#includeopencv2/opencv.hpp
using namespace std;
using namespace cv;/*
抖音特效蓝线挑战
算法原理1、将视频图像从顶-底或左-右逐行列扫描图像。2、将扫描完成的行列像素重新生成定格图像3、使用原帧图像像素填充未扫描到的像素
*///将两幅图像进行线性混合
bool Linear_Blend(Mat src1, Mat src2, Mat dst)
{/*参数说明src1生成的定格图像。由于生成的定格图像是从顶往下逐行扫描故在扫描线下的像素为0src2原视频帧图像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.atVec3b(i, j)[0] ! 0){dst.atVec3b(i, j)[c] src1.atVec3b(i, j)[c];}else{dst.atVec3b(i, j)[c] src2.atVec3b(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.atVec3b(h, j)[c] canvas.atVec3b(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;
}