Add center_video.cpp

This commit is contained in:
augustin64 2024-01-07 14:26:18 +01:00
parent 4a011689ab
commit 2301af6e2d

177
src/center_video.cpp Normal file
View File

@ -0,0 +1,177 @@
#include <opencv2/opencv.hpp>
#define WIDTH 1920
#define HEIGHT 1080
#define ACCEPTED_BLANK 20
#define ACCEPTED_NON_BG 10
#define SHOW_PROGRESS
using namespace std;
cv::Scalar backgroundColor(255, 255, 255);
cv::Scalar blue(249, 0, 0);
bool is_background (const cv::Vec3b& pixel) {
// Upper bound: 195075
return abs((pixel[0] - backgroundColor[0])*(pixel[1] - backgroundColor[1])*(pixel[2] - backgroundColor[2])) < 5000;
};
cv::Rect get_pos(const cv::Mat& frame) {
bool no_break = true;
int left_margin = -1;
int right_margin = -1;
for (int i=0; i < frame.cols; i++) {
bool contains_non_white = false;
for (int j=0; j < frame.rows; j++) {
int non_bg = 0;
if (!is_background(frame.at<cv::Vec3b>(j, i))) {
contains_non_white = true;
break;
}
}
if (no_break && !contains_non_white) {
left_margin += 1;
} else if (contains_non_white) {
no_break = false;
}
if (contains_non_white) {
right_margin = i+1;
}
}
right_margin = min(right_margin, frame.cols-1);
// Iterate over the lines and find the tallest block of non-white lines, this will give us
// the vertical size of the rectangle, i.e the top and bottom margins
int top_margin = -1;
int bottom_margin = -1;
int max_height = 0;
int cur_height = -1;
int cur_top_margin = 0;
int echecs = 0;
for (int i=0; i < frame.rows; i++) {
bool contains_non_white = false;
int non_bg = 0;
for (int j=0; j < frame.cols; j++) {
if (!is_background(frame.at<cv::Vec3b>(i, j))) {
if (++non_bg >= ACCEPTED_NON_BG) {
contains_non_white = true;
break;
}
}
}
if (!contains_non_white) {
if (++echecs >= ACCEPTED_BLANK) {
if (cur_height >= max_height) {
max_height = cur_height;
top_margin = cur_top_margin;
bottom_margin = cur_top_margin + cur_height;
}
cur_height = -1;
}
} else {
cur_height += 1;
if (cur_height == 0) {
cur_top_margin = i;
}
echecs = 0;
}
}
if (cur_height >= max_height) {
max_height = cur_height;
top_margin = cur_top_margin;
bottom_margin = cur_top_margin + cur_height;
}
//cout << "top: " << top_margin << ", bottom: " << bottom_margin << ", height: " << max_height << endl;
bottom_margin = min(bottom_margin, frame.rows-1);
cv::Rect rect = cv::Rect(left_margin, top_margin, right_margin-left_margin, bottom_margin-top_margin);
// Return a rectangle covering all the frame except the left margin
//cv::Rect rect = cv::Rect(left_margin, 0, right_margin-left_margin, frame.rows-1);
//cout << rect << endl;
return rect;
}
int main(int argc, char** argv) {
if (argc != 3) {
cerr << "Usage: " << argv[0] << " <input_video_file> <output_video_file>" << endl;
return 1;
}
// Open the input video file
cv::VideoCapture inputVideo(argv[1]);
if (!inputVideo.isOpened()) {
cerr << "Error: Could not open input video file." << endl;
return 1;
}
// Get input video properties
int inputWidth = inputVideo.get(cv::CAP_PROP_FRAME_WIDTH);
int inputHeight = inputVideo.get(cv::CAP_PROP_FRAME_HEIGHT);
int totalFrames = static_cast<int>(inputVideo.get(cv::CAP_PROP_FRAME_COUNT));
// Create video writer for the output video
cv::VideoWriter outputVideo(argv[2], cv::VideoWriter::fourcc('X', '2', '6', '4'), inputVideo.get(cv::CAP_PROP_FPS),
cv::Size(WIDTH, HEIGHT), true);
if (!outputVideo.isOpened()) {
cerr << "Error: Could not open output video file for writing." << endl;
return 1;
}
// Process each frame
cv::Mat frame;
int currentFrame = 0;
int last_progress = -1;
while (inputVideo.read(frame)) {
// Get the rectangle to keep using the get_pos function
cv::Rect roi = get_pos(frame);
cv::Mat resizedFrame(HEIGHT, WIDTH, frame.type(), blue);
frame(roi).copyTo(resizedFrame(cv::Rect((WIDTH - roi.width) / 2, (HEIGHT - roi.height) / 2, roi.width, roi.height)));
// Write the modified frame to the output video
outputVideo.write(resizedFrame);
// Update and display progress bar
currentFrame++;
#ifdef SHOW_PROGRESS
float progress = static_cast<float>(currentFrame) / totalFrames;
int barWidth = 50;
int pos = static_cast<int>(barWidth * progress);
int progress_percent = static_cast<int>(progress * 100.0);
if (progress_percent != last_progress) {
cout << "[";
for (int i = 0; i < barWidth; ++i) {
if (i < pos) cout << "=";
else if (i == pos) cout << ">";
else cout << " ";
}
cout << "] " << int(progress * 100.0) << "% " << roi << "\r";
cout.flush();
}
#endif
}
// Release video capture and writer objects
inputVideo.release();
outputVideo.release();
cout << "Video processing complete. Output saved to: " << argv[2] << endl;
return 0;
}