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) 错误。

相关推荐
黄林晴6 小时前
Google Play 发版链路全面重构:合规前置、审核自动化、生态全面收紧
android·google
gis分享者7 小时前
OpenCV 新手入门与实战部署指南
人工智能·opencv·计算机视觉
通玄8 小时前
Jetpack Compose 入门系列(四):动画基本使用
android
杉氧8 小时前
Kotlin 协程深度解析②:生存指南——掌握结构化并发的生命线
android·kotlin
故渊at8 小时前
第四板块:Android 输入系统与触控事件 | 第十五篇:InputReader 与 InputDispatcher 的触控流水线
android·anr·输入系统·inputdispatcher·inputreader·触控事件·inputevent
方白羽8 小时前
Vibe Coding 四个核心阶段
android·前端·app
潘潘潘10 小时前
Android网络结构分析——有线网络
android
踏雪羽翼10 小时前
Android OpenGL实现十几种美颜功能
android
Android小码家12 小时前
BootAnimation+SE+开机MP4动画播放
android·framework
加农炮手Jinx12 小时前
Flutter for OpenHarmony:pub_updater 命令行工具自动更新专家(DevOps 运维必备) 深度解析与鸿蒙适配指南
android·运维·网络·flutter·华为·harmonyos·devops