使用 opencv C++ 将图像连接成单个图像

concatenate the images to single image using opencv C++

我正在根据视频制作单张图片。但是我阅读视频并创建帧,然后旋转帧并裁剪帧,然后保存这些裁剪的帧。 这些裁剪后的帧应该组合起来创建一个图像。 所以我将它们附加到 Mat 的向量中,然后想水平连接它们。 我这样做了,但它没有显示任何图像,也没有保存图像。

我想做类似于python

的事情
list_images = []
for img in glob.glob(crop_dir + "*.jpg"):
 n = cv2.imread(img,0)
 list_images.append(n)
im_v = np.concatenate(list_images)
cv2.imwrite("finalimg.jpg",im_v)

我的变量imglist是类型 class std::vector<class cv::Mat,class std::allocator<class cv::Mat> >

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <filesystem>

using namespace std;
using namespace cv;
namespace fs = std::filesystem;

string crop_dir = "Task2_Resources/CropImages/";

void delete_dir_content(const fs::path& dir_path) {
    for (auto& path : fs::directory_iterator(dir_path)) {
        fs::remove_all(path);
    }
}

int main() {

    system("CLS");

    if (!fs::is_directory(crop_dir) || !fs::exists(crop_dir)) { // Check if  folder exists
        fs::create_directory(crop_dir); // create  folder
    }
    delete_dir_content(crop_dir);

    VideoCapture vid_capture("Task2_Resources/sample201.avi");

    int count = 0;
    Mat finalimg,mimg;
    vector<cv::Mat> imglist;
    
    Mat image;
    int x = 190, y = 59, h = 1, w = 962;

    if (!vid_capture.isOpened()){
        std::cout << "Cannot open the video file" << endl;
        return -1;
    }
    
    while (true) {

        Mat frame , rimg;
        vector<Mat> blocks;
        
        
        bool isSuccess = vid_capture.read(frame);
        if (!isSuccess){
            std::cout << "Cannot read the frame from video file" << endl;
            break;
        }

        //imshow("Frames", frame);
        count++;
        float width = frame.cols;
        float height = frame.rows;
        Point2f center = Point2f((width / 2), (height / 2));
        double degree = -0.2;
        double scale = 1.0;
        Mat change = getRotationMatrix2D(center, degree, scale);  // Rotate & scale 
        warpAffine(frame, rimg, change, frame.size(), cv::INTER_CUBIC, cv::BORDER_CONSTANT, cv::Scalar(0, 0, 0));
        Mat cropped_image = rimg(Range(y,y+h), Range(x, x+w));

        string fname = to_string(count) + ".jpg";
        cv::imwrite(crop_dir + fname, cropped_image);    
        imglist.push_back(cropped_image);



    }
     
    hconcat(imglist,image);
   
   cout << typeid(imglist).name() << endl;
    cv::imwrite("final.jpg", image);
    std::cout << "Total frames created " << count << endl;

    return 0;
}

Visual Studio 调试控制台

我唯一注意到的问题是 h = 1 - 这使得 cropped_image 的高度只有 1 个像素。

由于您没有报告任何错误消息,我们无法真正说明它为什么不起作用。
我建议您使用调试器,并逐步迭代代码(为此使用 IDE)。

要构建工作示例,您可以按照接下来描述的阶段进行操作。


其中一个问题可能与 sample201.avi 视频文件有关。
为了使答案可重现,我们可以使用 FFmpeg CLI 来创建合成视频文件:

请从控制台执行以下命令(所以我们有相同的输入文件):

ffmpeg -y -f lavfi -i testsrc=size=1280x720:duration=3:rate=1 sample.avi

该命令创建一个具有 3 个视频帧且分辨率为 1280x720 的视频文件。
如果您使用 Windows,您可能需要下载 FFmpeg(在 Linux 中,ffmpeg 通常是“内置的”)。

sample.avi 复制到 Task2_Resources 文件夹。


编辑您的 C++ 代码:
int x = 190, y = 59, h = 1, w = 962; 替换为:

int x = 190, y = 59, h = 500, w = 962;

(例如使用 500 像素的高度)。

VideoCapture vid_capture("Task2_Resources/sample201.avi");替换为VideoCapture vid_capture("Task2_Resources/sample.avi");


执行你的代码。
确保在 CropImages 文件夹中创建了 3 张 JPG 图片。

输出文件 final.jpg 在工作文件夹中创建(确保您具有写入权限)。


示例输出(调整大小):