当前位置:   article > 正文

OpenCV+C++实现视频字符画(附源码)_c++字符串动画

c++字符串动画

字符画实现基本思路

萌新小白为了实现这个功能真的是百度了很久很久,看了很多大佬的文章,终于我成功了Ψ( ̄∀ ̄)Ψ。现在来分享一下我的大致思路。

思路分析

若相对整个视频进行字符画处理,则需要对视频的每一帧进行处理,读取视频的每一帧的代码如下:

VideoCapture cap;
cap.open("F:/opencv/images/test01.MP4");
if (!cap.isOpened()) {
	cout << "can't open file" << endl;
	return -1;
}
Mat frame, frame_resize, frame_gray;
while (true)
{
	cap >> frame;
	if (frame.empty())	break;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

因为要输出原始图像的大小,我们需要对图像的尺寸进行重新调整,然后将图片转换为灰度图(后面需要根据灰度等级选择字符):

resize(frame, frame_resize, Size(300, 90));
cvtColor(frame_resize, frame_gray, COLOR_BGR2GRAY);
  • 1
  • 2

接下来就是要对图像的每个像素进行遍历,根据灰度等级划分字符,如果想要更加明显的效果可以选用更多的字符。

因为最后要将字符串进行输出,所以我们首先对字符串进行初始化,然后依次加上每个像素的字符。

String txt = "";
int height = frame_gray.rows;
int width = frame_gray.cols;

for (int j = 0; j < height; j++) {
	for (int i = 0; i < width; i++)
	{
		int pdata = frame_gray.ptr<uchar>(j)[i];
		if (pdata == 255)
			txt += char_list[87];
		else
			txt += char_list[pdata / len];
	}
	txt += "\n";
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

这样的话一帧就处理好啦,紧接着直接将字符串直接进行输出就可以了:

cout << txt;//输出当前字符
  • 1

如果你看到这里就去尝试的话,很快就会发现输出的字符串很吓人,让你眼花缭乱Σ(っ °Д °;)っ。这是因为在你的编译器中,字符默认大小比较大,而一张图像又有很多个像素,图像肯定会变大了,解决这个问题的最好办法就是直接改变编译器输出的字体大小

我用的是VS2019,可以右键单击控制台窗口后点击默认值,会出来这个窗口:
在这里插入图片描述
我这里将字体大小改为了5,你们可以根据自己视频的情况进行更改,只要能让窗口大小大于一帧字符串的大小即可。

然后我们就实现了基本的字符画功能了ψ(`∇´)ψ,但是可能细心的小朋友又会发现字符画视频显示的很不稳定,甚至闪的眼睛疼。这个时候我们可以在程序里面加点内容就好啦:

//将光标移动到(0,0)处
HANDLE hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos;
pos.X = 0;
pos.Y = 0;
SetConsoleCursorPosition(hConsoleOutput, pos);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

每次改变帧数的时候都将光标移动到(0, 0)处,大家再也不用担心闪眼睛了w(゚Д゚)w。代码参考了好多大佬的文章,附上一张我自己测试的图片啊:
在这里插入图片描述
不知道能不能看出来这是一坨什么w(゚Д゚)w,好吧其实它是奥特曼里面的怪兽。

源代码

#include <opencv2/opencv.hpp>
#include <iostream>
#include <Windows.h>

using namespace cv;
using namespace std;

const char* char_list = " .,-'`:!1+*abcdefghijklmnopqrstuvwxyz<>()\/{}[]?234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ%&@#$";
int len = 255 / strlen(char_list);
int main()
{
	VideoCapture cap;
	cap.open("F:/opencv/images/test01.MP4");
	if (!cap.isOpened()) {
		cout << "can't open file" << endl;
		return -1;
	}
	Mat frame, frame_resize, frame_gray;
	while (true)
	{
		cap >> frame;
		if (frame.empty())	break;
		resize(frame, frame_resize, Size(300, 90));
		cvtColor(frame_resize, frame_gray, COLOR_BGR2GRAY);
		String txt = "";

		int height = frame_gray.rows;
		int width = frame_gray.cols;

		for (int j = 0; j < height; j++) {
			for (int i = 0; i < width; i++)
			{
				int pdata = frame_gray.ptr<uchar>(j)[i];
				if (pdata == 255)
					txt += char_list[87];
				else
					txt += char_list[pdata / len];
			}
			txt += "\n";
		}

		//将光标移动到(0,0)处
		HANDLE hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
		COORD pos;
		pos.X = 0;
		pos.Y = 0;
		SetConsoleCursorPosition(hConsoleOutput, pos);
		
		//输出当前字符
		cout << txt;
	}
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/94271?site
推荐阅读
相关标签
  

闽ICP备14008679号