Android opencv使用Core.hconcat 进行图像拼接

Android 集成OpenCV-CSDN博客

java 复制代码
import org.opencv.android.Utils;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.imgcodecs.Imgcodecs;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
import android.widget.ImageView;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

public class ImageStitchingActivity extends AppCompatActivity {

    private static final String TAG = "ImageStitchingActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main); // 你的布局文件

        ImageView imageView = findViewById(R.id.imageView); // 你的ImageView

        try {
            Bitmap bitmap1 = loadBitmapFromResource(R.drawable.image1); // 替换成你的资源ID
            Bitmap bitmap2 = loadBitmapFromResource(R.drawable.image2); // 替换成你的资源ID

            if (bitmap1 == null || bitmap2 == null) {
                Log.e(TAG, "图像加载失败");
                return;
            }

            Mat mat1 = convertBitmapToMat(bitmap1);
            Mat mat2 = convertBitmapToMat(bitmap2);

            if (mat1 == null || mat2 == null) {
                Log.e(TAG, "Bitmap 转 Mat 失败");
                return;
            }

            Mat stitchedMat = stitchImages(mat1, mat2);

            if (stitchedMat == null) {
                Log.e(TAG, "图像拼接失败");
                return;
            }

            Bitmap stitchedBitmap = convertMatToBitmap(stitchedMat);

            if (stitchedBitmap == null) {
                Log.e(TAG, "Mat 转 Bitmap 失败");
                return;
            }

            imageView.setImageBitmap(stitchedBitmap);


            // 释放资源
            mat1.release();
            mat2.release();
            stitchedMat.release();
            bitmap1.recycle();
            bitmap2.recycle();


        } catch (Exception e) {
            Log.e(TAG, "拼接过程中出现错误: " + e.getMessage());
            // 处理异常,例如显示错误消息
        }
    }

    private Bitmap loadBitmapFromResource(int resourceId) {
        InputStream inputStream = getResources().openRawResource(resourceId);
        try {
            return BitmapFactory.decodeStream(inputStream);
        } catch (Exception e) {
            Log.e(TAG, "资源加载失败", e);
            return null;
        } finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                Log.e(TAG, "流关闭失败", e);
            }
        }
    }


    private Mat convertBitmapToMat(Bitmap bitmap) {
        Mat mat = new Mat();
        Utils.bitmapToMat(bitmap, mat);
        return mat;
    }

    private Bitmap convertMatToBitmap(Mat mat) {
        Bitmap bitmap = Bitmap.createBitmap(mat.cols(), mat.rows(), Bitmap.Config.ARGB_8888);
        Utils.matToBitmap(mat, bitmap);
        return bitmap;
    }

    private Mat stitchImages(Mat mat1, Mat mat2) {
        if (mat1.rows() != mat2.rows()) {
            Log.e(TAG, "图像高度不一致,无法拼接");
            return null;
        }
        List<Mat> mats = new ArrayList<>();
        mats.add(mat1);
        mats.add(mat2);
        Mat stitchedMat = new Mat();
        Core.hconcat(mats, stitchedMat);
        return stitchedMat;
    }
}

代码说明:

  • 错误处理: 代码中加入了大量的错误检查,例如图像加载失败、Bitmap 到 Mat 的转换失败、图像高度不一致等情况,并在发生错误时打印日志信息并返回,避免程序崩溃。
  • 资源释放: mat1.release(), mat2.release(), stitchedMat.release(), bitmap1.recycle(), bitmap2.recycle() 这些语句用于释放资源,防止内存泄漏。
  • 类型转换: convertBitmapToMatconvertMatToBitmap 函数封装了 Bitmap 和 Mat 之间的转换,提高代码可读性和可维护性。
  • 图像加载: 使用 loadBitmapFromResource 函数从资源加载图片,并进行错误处理。
  • 高度一致性检查:stitchImages 函数中,添加了对输入图像高度是否一致的检查,这是 Core.hconcat 的必要条件。

使用前请注意:

  • 替换 R.drawable.image1R.drawable.image2 为你实际的图像资源 ID。
  • 确保你的项目已正确配置 OpenCV 库。
  • 在你的布局文件中添加一个 ImageView,并在代码中使用 findViewById 获取其引用。

这个改进后的代码更加健壮,可以更好地避免运行时崩溃,并提供更清晰的错误信息。 即使出现错误,它也只会打印日志并停止执行,不会导致应用程序崩溃。 记住,在处理大型图像时,尤其要注意内存管理,避免内存溢出 (OOM) 错误。

相关推荐
xiaoshiquan120625 分钟前
as强制过滤指定依赖版本库,解决该依赖不同版本冲突
android
2501_929157682 小时前
Switch 20.5.0系统最新PSP模拟器懒人包
android·游戏·ios·pdf
用户094 小时前
Kotlin Flow的6个必知高阶技巧
android·面试·kotlin
用户094 小时前
Flutter插件与包的本质差异
android·flutter·面试
用户094 小时前
Jetpack Compose静态与动态CompositionLocal深度解析
android·面试·kotlin
聆风吟º7 小时前
【Spring Boot 报错已解决】别让端口配置卡壳!Spring Boot “Binding to target failed” 报错解决思路
android·java·spring boot
非专业程序员Ping14 小时前
HarfBuzz概览
android·ios·swift·font
Jeled15 小时前
「高级 Android 架构师成长路线」的第 1 阶段 —— 强化体系与架构思维(Clean Architecture 实战)
android·kotlin·android studio·1024程序员节
明道源码17 小时前
Kotlin 控制流、函数、Lambda、高阶函数
android·开发语言·kotlin
Antonio91518 小时前
【图像处理】灰度图像与二值化
图像处理·opencv