OpenCV实现任意大小图片的合并

OpenCV实现图像合并主要有两种方法
方法一:使用Mat.push_back方法将列数相同的图像加到最后一行
方法二: 主要思路是将图像拷贝到待合并图像的感兴趣区域
(1)新建一个要合并的图像(容器)
(2)在新建合并图像中设置感兴趣区域
(3)将待拷贝图像拷贝到感性趣区域中

法1.使用Mat.push_back方法将列数相同的图像加到最后一行

注意此方法只能将图像合并到底部
示例代码:

#include<cv.h>
#include<highgui.h>
using namespace cv;

int main()
{
    Mat image1=imread("1.jpg");
    Mat image2=imread("2.jpg");
    if (image1.empty() || image2.empty())
    {
        printf("open error");
        return 0;
    }
    //push_back 方法将图像2拷贝到图像1的最后一行
    Mat img_merge;
    img_merge.push_back(image1);
    img_merge.push_back(image2);

    namedWindow("img_merge", 0);
    imshow("img_merge", img_merge);

    waitKey();
    return 0;
}

法2.将图像拷贝到待合并图像的感兴趣区域

此方法可以将图像拷贝到任意区域,位置由感兴趣区域决定
示例代码:

#include<cv.h>
#include<highgui.h>
using namespace cv;

int main()
{
    Mat image1=imread("1.jpg");
    Mat image2=imread("2.jpg");
    if (image1.empty() || image2.empty())
    {
        printf("open error");
        return 0;
    }
    //1.新建一个要合并的图像
    Mat img_merge;
    Size size(image1.cols + image2.cols, MAX(image1.rows, image1.rows));
    img_merge.create(size, CV_MAKETYPE(image1.depth(), 3));
    img_merge = Scalar::all(0);
    Mat outImg_left, outImg_right;
    //2.在新建合并图像中设置感兴趣区域
    outImg_left = img_merge(Rect(0, 0, image1.cols, image1.rows));
    outImg_right = img_merge(Rect(image1.cols, 0, image1.cols, image1.rows));
    //3.将待拷贝图像拷贝到感性趣区域中
    image1.copyTo(outImg_left);
    image2.copyTo(outImg_right);
    namedWindow("image1", 0);
    imshow("image1", img_merge);
    waitKey();
    return 0;
}

最后上两张合并后的图片
方法1合成效果如图
这里写图片描述
方法2合成效果如图
这里写图片描述

  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是使用C、OpenCV和OpenMP实现的连通区域标记的两遍扫描算法。该算法使用动态数组来存储标记结果,并使用OpenCV的窗口显示结果。 ``` #include <stdio.h> #include <stdlib.h> #include <omp.h> #include <opencv2/opencv.hpp> using namespace cv; int main(int argc, char** argv) { // Load input image Mat image = imread("input.jpg", IMREAD_GRAYSCALE); if (image.empty()) { printf("Could not open or find the image.\n"); return -1; } // Initialize variables int width = image.cols; int height = image.rows; int num_labels = 0; int* labels = (int*)malloc(width * height * sizeof(int)); int* label_map = (int*)malloc((width * height / 4) * sizeof(int)); memset(labels, 0, width * height * sizeof(int)); memset(label_map, 0, (width * height / 4) * sizeof(int)); // First pass #pragma omp parallel for for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { if (image.at<uchar>(y, x) > 0) { int label = 0; if (x > 0 && labels[y * width + x - 1] > 0) { label = labels[y * width + x - 1]; } if (y > 0 && labels[(y - 1) * width + x] > 0 && (label == 0 || label > labels[(y - 1) * width + x])) { label = labels[(y - 1) * width + x]; } if (label == 0) { #pragma omp atomic capture { num_labels++; label = num_labels; } } labels[y * width + x] = label; } } } // Second pass #pragma omp parallel for for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { if (labels[y * width + x] > 0) { int label = labels[y * width + x]; int min_label = label; while (label_map[min_label] > 0) { min_label = label_map[min_label]; } if (min_label != label) { label_map[label] = min_label; } labels[y * width + x] = min_label; } } } // Merge labels for (int i = 1; i <= num_labels; i++) { while (label_map[i] > 0) { i = label_map[i]; } label_map[i] = i; } // Colorize labels Mat output = Mat::zeros(height, width, CV_8UC3); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { if (labels[y * width + x] > 0) { int label = label_map[labels[y * width + x]]; Vec3b color; color[0] = label * 50 % 255; color[1] = label * 70 % 255; color[2] = label * 90 % 255; output.at<Vec3b>(y, x) = color; } } } // Display result namedWindow("Result", WINDOW_NORMAL); imshow("Result", output); waitKey(0); // Free memory free(labels); free(label_map); return 0; } ``` 该算法的实现基于以下步骤: 1. 加载输入图像并初始化变量。 2. 第一遍扫描:对于每个非零像素,将其与左侧和上方的像素进行比较,选择具有最小标记的那个像素,并将其标记为当前像素的标记。如果没有邻居像素被标记,则将当前像素分配一个新的标记。 3. 第二遍扫描:对于每个非零像素,将其标记更新为与其最小标记邻居相同的标记。为此,使用一个映射数组来记录标记之间的关系。如果两个标记被合并,则将一个标记映射到另一个标记。 4. 合并标记:将所有标记映射到其最小标记。 5. 给标记着色:将每个标记分配一个随机颜色,并将其应用于对应的像素。 6. 显示结果并释放内存。 该算法的主要优点是它在处理大型图像时具有很好的性能,因为它使用了OpenMP来并行化处理。此外,该算法使用动态数组来存储标记结果,因此可以处理任意大小的图像。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值