According to the shooting speed of the area array camera and the speed of the conveyor belt movement, each frame of the physical picture is seamlessly spliced to make it a complete picture. The whole process and c++ code

Note: This article only provides a simple implementation method and process of this project, as follows:

  1. Initialize camera parameters, including exposure time, backlight compensation, etc.
  2. Initialize the conveyor controller and set the conveyor speed.
  3. Start capturing images and save each frame.
  4. For each frame, it is registered with the previous frame (eg using SIFT algorithm).
  5. Based on the registration result, the current frame is transformed, and it is seamlessly stitched with the previous frame.
  6. Save the stitched image as the final output.

There are similar stitching methods in opencv, such as panoramic stitching, because panoramic stitching is a stitching method based on feature point matching. If this method is available for simple stitching, let's look at a simple code program

// OpenCV库
#include <opencv2/opencv.hpp>

using namespace cv;

int main(int argc, char** argv) {
    // 初始化相机参数
    int exposure_time = 100;    // 曝光时间(以毫秒为单位)
    int gain = 0;
    bool backlight_compensation = true;

    // 初始化传送带控制器
    double conveyor_speed = 0.5;    // 传送带速度(以米/秒为单位)

    // 定义图像存储数组
    const int num_frames = 100;
    Mat frames[num_frames];

    // 初始化相机
    VideoCapture cap(0);
    cap.set(CV_CAP_PROP_FRAME_WIDTH, 640);
    cap.set(CV_CAP_PROP_FRAME_HEIGHT, 480);
    cap.set(CV_CAP_PROP_EXPOSURE, exposure_time);
    cap.set(CV_CAP_PROP_GAIN, gain);
    cap.set(CV_CAP_PROP_BACKLIGHT, backlight_compensation);

    // 等待相机初始化完成
    std::this_thread::sleep_for(std::chrono::milliseconds(2000));

    // 开始捕获图像并保存每一帧
    for (int i = 0; i < num_frames; ++i) {
        cap >> frames[i];
        std::string filename = "frame_" + std::to_string(i) + ".jpg";
        imwrite(filename, frames[i]);

        // 控制传送带运动
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
        // TODO: 控制传送带运动

        // 配准前一帧
        if (i > 0) {
            // 利用SIFT算法进行特征点匹配和变换估计
            Ptr<FeatureDetector> detector = SIFT::create();
            std::vector<KeyPoint> keypoints1, keypoints2;
            Mat descriptors1, descriptors2;
            detector->detectAndCompute(frames[i-1], Mat(), keypoints1, descriptors1);
            detector->detectAndCompute(frames[i], Mat(), keypoints2, descriptors2);

    // 利用FLANN库进行匹配
            FlannBasedMatcher matcher;
            std::vector<DMatch> matches;
            matcher.match(descriptors1, descriptors2, matches);

            // 提取匹配结果中的特征点对
            std::vector<Point2f> pts1, pts2;
            for (size_t j=0; j<matches.size(); ++j) {
                pts1.push_back(keypoints1[matches[j].queryIdx].pt);
                pts2.push_back(keypoints2[matches[j].trainIdx].pt);
            }

    // 利用findHomography函数进行变换估计
            Mat H = findHomography(pts1, pts2, RANSAC);

            // 对当前帧进行变换
            warpPerspective(frames[i], frames[i], H, Size(frames[i].cols,frames[i].rows));
        }

        // 向左移动前一帧的ROI,然后将当前帧拼接到其右侧
        Rect roi(0, 0, i*frames[i].cols, frames[i].rows);
        Mat dst = Mat::zeros(frames[i].rows, (i+1)*frames[i].cols, frames[i].type());
        frames[i-1](roi).copyTo(dst(Rect(0, 0, i*frames[i].cols, frames[i].rows)));
        frames[i].copyTo(dst(Rect(i*frames[i].cols, 0, frames[i].cols, frames[i].rows)));
        frames[i] = dst.clone();
    }

    // 将拼接后的图像保存为最终输出
    imwrite("output.jpg", frames[num_frames-1]);

    return 0;
}

This program is currently in the research stage, please look forward to the follow-up updates, if you have good suggestions for code friends, welcome to discuss in the comment area, all Chinese people should not see outsiders, make progress together, and make money! !

Guess you like

Origin blog.csdn.net/qq_65356682/article/details/130139386