赞
踩
萌新小白为了实现这个功能真的是百度了很久很久,看了很多大佬的文章,终于我成功了Ψ( ̄∀ ̄)Ψ。现在来分享一下我的大致思路。
若相对整个视频进行字符画处理,则需要对视频的每一帧进行处理,读取视频的每一帧的代码如下:
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";
}
这样的话一帧就处理好啦,紧接着直接将字符串直接进行输出就可以了:
cout << txt;//输出当前字符
如果你看到这里就去尝试的话,很快就会发现输出的字符串很吓人,让你眼花缭乱Σ(っ °Д °;)っ。这是因为在你的编译器中,字符默认大小比较大,而一张图像又有很多个像素,图像肯定会变大了,解决这个问题的最好办法就是直接改变编译器输出的字体大小。
我用的是VS2019,可以右键单击控制台窗口后点击默认值,会出来这个窗口:
我这里将字体大小改为了5,你们可以根据自己视频的情况进行更改,只要能让窗口大小大于一帧字符串的大小即可。
然后我们就实现了基本的字符画功能了ψ(`∇´)ψ,但是可能细心的小朋友又会发现字符画视频显示的很不稳定,甚至闪的眼睛疼。这个时候我们可以在程序里面加点内容就好啦:
//将光标移动到(0,0)处
HANDLE hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos;
pos.X = 0;
pos.Y = 0;
SetConsoleCursorPosition(hConsoleOutput, pos);
每次改变帧数的时候都将光标移动到(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; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。