Loading...
Searching...
No Matches
Font-Demo
Prev Tutorial: Shader-Demo
Next Tutorial: Pedestrian-Demo
Original author | Amir Hassan (kallaballa) amir@.nosp@m.viel.nosp@m.-zu.o.nosp@m.rg |
Compatibility | OpenCV >= 4.7 |
Renders a Star Wars like text crawl using nanovg (OpenGL) and uses OpenCV for a pseudo 3D effect.
Downloading...
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
// Copyright Amir Hassan (kallaballa) <amir@viel-zu.org>
#include <opencv2/v4d/v4d.hpp>
#include <string>
#include <algorithm>
#include <vector>
#include <sstream>
#include <limits>
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif
/* Demo parameters */
#ifndef __EMSCRIPTEN__
constexpr long unsigned int WIDTH = 1280;
constexpr long unsigned int HEIGHT = 720;
#else
constexpr long unsigned int WIDTH = 960;
constexpr long unsigned int HEIGHT = 960;
#endif
constexpr bool OFFSCREEN = false;
#ifndef __EMSCRIPTEN__
constexpr const char* OUTPUT_FILENAME = "font-demo.mkv";
constexpr double FPS = 60;
#endif
const cv::Scalar_<float> INITIAL_COLOR = cv::v4d::colorConvert(cv::Scalar(0.15 * 180.0, 128, 255, 255), cv::COLOR_HLS2BGR);
/* Visualization parameters */
float min_star_size = 0.5f;
float max_star_size = 1.5f;
int min_star_count = 1000;
int max_star_count = 3000;
float star_alpha = 0.3f;
float font_size = 40.0f;
float text_color[4] = {INITIAL_COLOR[2] / 255.0f, INITIAL_COLOR[1] / 255.0f, INITIAL_COLOR[0] / 255.0f, INITIAL_COLOR[3] / 255.0f};
float warp_ratio = 1.0f/3.0f;
bool show_fps = true;
using std::cerr;
using std::endl;
using std::string;
using std::vector;
using std::istringstream;
vector<string> lines;
bool update_stars = true;
bool update_perspective = true;
using namespace cv::v4d;
window->imgui([](ImGuiContext* ctx){
using namespace ImGui;
SetCurrentContext(ctx);
Begin("Effect");
Text("Text Crawl");
SliderFloat("Font Size", &font_size, 1.0f, 100.0f);
if(SliderFloat("Warp Ratio", &warp_ratio, 0.1f, 1.0f))
update_perspective = true;
ColorPicker4("Text Color", text_color);
Text("Stars");
if(SliderFloat("Min Star Size", &min_star_size, 0.5f, 1.0f))
update_stars = true;
if(SliderFloat("Max Star Size", &max_star_size, 1.0f, 10.0f))
update_stars = true;
if(SliderInt("Min Star Count", &min_star_count, 1, 1000))
update_stars = true;
if(SliderInt("Max Star Count", &max_star_count, 1000, 5000))
update_stars = true;
if(SliderFloat("Min Star Alpha", &star_alpha, 0.2f, 1.0f))
update_stars = true;
End();
});
}
//BGRA
static cv::UMat stars, warped;
//transformation matrix
static cv::Mat tm;
//line count
static uint32_t cnt = 0;
//Total number of lines in the text
static int32_t numLines = lines.size();
//Height of the text in pixels
static int32_t textHeight = (numLines * font_size);
//y-value of the current line
static int32_t y = 0;
//How many pixels to translate the text up.
int32_t translateY = HEIGHT - cnt;
if(update_stars) {
window->nvg([&](const cv::Size& sz) {
using namespace cv::v4d::nvg;
clear();
//draw stars
int numStars = rng.uniform(min_star_count, max_star_count);
for(int i = 0; i < numStars; ++i) {
beginPath();
strokeWidth(size);
strokeColor(cv::Scalar(255, 255, 255, star_alpha * 255.0f));
stroke();
}
});
window->fb([&](cv::UMat& frameBuffer){
frameBuffer.copyTo(stars);
});
update_stars = false;
}
if(update_perspective) {
//Derive the transformation matrix tm for the pseudo 3D effect from quad1 and quad2.
vector<cv::Point2f> quad1 = {{0,0},{WIDTH,0},{WIDTH,HEIGHT},{0,HEIGHT}};
float l = (WIDTH - (WIDTH * warp_ratio)) / 2.0;
float r = WIDTH - l;
vector<cv::Point2f> quad2 = {{l, 0.0f},{r, 0.0f},{WIDTH,HEIGHT},{0,HEIGHT}};
tm = cv::getPerspectiveTransform(quad1, quad2);
update_perspective = false;
}
window->nvg([&](const cv::Size& sz) {
using namespace cv::v4d::nvg;
clear();
fontSize(font_size);
fontFace("sans-bold");
fillColor(cv::Scalar(text_color[2] * 255.0f, text_color[1] * 255.0f, text_color[0] * 255.0f, text_color[3] * 255.0f));
textAlign(NVG_ALIGN_CENTER | NVG_ALIGN_TOP);
translate(0, translateY);
for (size_t i = 0; i < lines.size(); ++i) {
y = (i * font_size);
if (y + translateY < textHeight && y + translateY + font_size > 0) {
}
}
});
window->fb([&](cv::UMat& framebuffer) {
//Pseudo 3D text effect.
cv::warpPerspective(framebuffer, warped, tm, framebuffer.size(), cv::INTER_LINEAR, cv::BORDER_CONSTANT, cv::Scalar());
//Combine layers
cv::add(stars, warped, framebuffer);
});
if(-translateY > textHeight) {
//reset the scroll once the text is out of the picture
cnt = 0;
}
window->write();
++cnt;
//Wrap the cnt around if it becomes to big.
if(cnt > std::numeric_limits<size_t>().max() / 2.0)
cnt = 0;
return window->display();
}
int main() {
try {
if(!OFFSCREEN) {
setup_gui(window);
}
window->printSystemInfo();
//The text to display
string txt = cv::getBuildInformation();
//Save the text to a vector
std::istringstream iss(txt);
for (std::string line; std::getline(iss, line); ) {
lines.push_back(line);
}
#ifndef __EMSCRIPTEN__
window->setSink(sink);
#endif
window->run(iteration);
} catch(std::exception& ex) {
cerr << "Exception: " << ex.what() << endl;
}
return 0;
}
Definition: mat.hpp:2432
MatSize size
dimensional size of the matrix; accessible in various formats
Definition: mat.hpp:2643
Definition: sink.hpp:19
void add(InputArray src1, InputArray src2, OutputArray dst, InputArray mask=noArray(), int dtype=-1)
Calculates the per-element sum of two arrays or an array and a scalar.
@ BORDER_CONSTANT
iiiiii|abcdefgh|iiiiiii with some specified i
Definition: base.hpp:269
const String & getBuildInformation()
Returns full configuration time cmake output.
@ COLOR_HLS2BGR
backward conversions HLS to RGB/BGR with H range 0..180 if 8 bit image
Definition: imgproc.hpp:616
Mat getPerspectiveTransform(InputArray src, InputArray dst, int solveMethod=DECOMP_LU)
Calculates a perspective transform from four pairs of the corresponding points.
void warpPerspective(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, const Scalar &borderValue=Scalar())
Applies a perspective transformation to an image.
Definition: nvg.hpp:19
void textAlign(int align)
void translate(float x, float y)
void beginPath()
void fontSize(float size)
void fontFace(const char *font)
void strokeColor(const cv::Scalar &bgra)
void fillColor(const cv::Scalar &color)
void clear(const cv::Scalar &bgra=cv::Scalar(0, 0, 0, 255))
float text(float x, float y, const char *string, const char *end)
void stroke()
void strokeWidth(float size)
Definition: framebuffercontext.hpp:25
cv::Scalar colorConvert(const cv::Scalar &src, cv::ColorConversionCodes code)
Sink makeWriterSink(const string &outputFilename, const float fps, const cv::Size &frameSize)