diff --git a/src/center_video.cpp b/src/center_video.cpp new file mode 100644 index 0000000..b8f2c5f --- /dev/null +++ b/src/center_video.cpp @@ -0,0 +1,177 @@ +#include + +#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(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(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] << " " << 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(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(currentFrame) / totalFrames; + int barWidth = 50; + int pos = static_cast(barWidth * progress); + + int progress_percent = static_cast(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; +}