rainyl / opencv_dart

OpenCV bindings for Dart language and Flutter. Support Asynchronous Now!
https://pub.dev/packages/opencv_dart
Apache License 2.0
136 stars 18 forks source link

Issue while trying to stitch photos on Android device in flutter app #179

Closed GoxeeVladan closed 3 months ago

GoxeeVladan commented 4 months ago

Read README carefully first Star :star: this project if you want to ask a question, no star, no answer

Question

So i have a question on how to workaround this error i get when i try to stitch images: E/linker (15518): library "/system/vendor/lib/libOpenCL.so" ("/vendor/lib/libOpenCL.so") needed or dlopened by "/data/app/67wySL_d8_JZcyMgMvVaWw==/{app bundle id}skSn_oIwPiKc5JBH85EMGw==/base.apk!/lib/arm64-v8a/libopencv_dart.so" is not accessible for the namespace: [name="clns-4", ld_library_paths="", default_library_paths="/data/app/67wySL_d8_JZcyMgMvVaWw==/{app bundle id}? Is it something known or is it me that does something wrong?

rainyl commented 3 months ago

Could you please provide a reproducible example?

GoxeeVladan commented 3 months ago

Here is the code where i'm using it:

import 'dart:io';

import 'package:camera/camera.dart'; import 'package:gallery_saver/gallery_saver.dart'; import 'package:get/get.dart'; import 'package:intel_booth_app/photos/car_images_list_view_model.dart'; import 'package:opencv_dart/opencv_dart.dart'; import 'package:path/path.dart'; import 'package:path_provider/path_provider.dart'; import 'package:path/path.dart' as path;

class Camera360Controller extends GetxController { var progressPercentage = 0.obs; var cameras = [].obs; final carImagesListViewModel = Get.find(); final RxList imagePaths = [].obs; var cameraController = Rx<CameraController?>(null); var isCapturing = false.obs;

@override void onInit() { super.onInit(); initializeCamera(); }

Future initializeCamera() async { cameras.value = await availableCameras(); if (cameras.isNotEmpty) { cameraController(CameraController(cameras.first, ResolutionPreset.high)); await cameraController.value?.initialize(); cameraController.refresh(); update(); } }

Future startCapturing() async { isCapturing.value = true; progressPercentage.value = 0; await captureAndStitchImages(); // Logic to capture and stitch images using opencv_dart will be implemented here }

void updateProgress(int value) { progressPercentage.value = value; }

Future captureAndStitchImages() async { List imagePaths = []; final directory = await getApplicationDocumentsDirectory(); for (int i = 0; i < 10; i++) { if (!isCapturing.value) break;

  final path = join(directory.path, '${DateTime.now().millisecondsSinceEpoch}.jpg');

  await cameraController.value?.takePicture();
  imagePaths.add(path);
  updateProgress((i + 1));
  await Future.delayed(const Duration(seconds: 100));
}

try {
  // Use opencv_dart to stitch images
  final stitchedImageBytes = await stitchImages(imagePaths);

  // Save the stitched image
  final stitchedImagePath = join(directory.path, 'stitched_panorama.jpg');
  final stitchedImageFile = File(stitchedImagePath);
  await stitchedImageFile.writeAsBytes(stitchedImageBytes);

  // Save to gallery
  await GallerySaver.saveImage(stitchedImagePath);

  // Upload the image using CarImagesListViewModel
  carImagesListViewModel.uploadImage(File(stitchedImagePath));

  // Navigate back to CarImagesScreen
  Get.back();
} catch (e) {
  isCapturing.value = false;
  print('Error stitching images: $e');
} finally {
  isCapturing.value = false;
  update();
}

}

Future<List> stitchImages(List imagePaths) async { List images = [];

for (String path in imagePaths) {
  Mat image = imread(path);
  images.add(image);
}

var stitched = Stitcher.create().stitch(VecMat.fromList(images));

List<int> stitchedBytes = imencode('.jpg', stitched.$2).$2;

return stitchedBytes;

}

@override void onClose() { cameraController.value?.dispose(); super.onClose(); } }

and the screen where it's called:

class CameraPage extends GetView { const CameraPage({super.key});

@override Widget build(BuildContext context) { final Camera360Controller controller = Get.find();

return Scaffold(
  backgroundColor: Colors.transparent,
  appBar: AppBar(
    flexibleSpace: Container(
      decoration: const BoxDecoration(
        gradient: LinearGradient(
          begin: Alignment.centerLeft,
          end: Alignment.centerRight,
          colors: <Color>[
            Color(0xFF335ae9),
            Color(0xFF34baff),
          ],
        ),
      ),
    ),
    leading: IconButton(
      padding: EdgeInsets.zero,
      icon: const Icon(
        Icons.arrow_back_ios_rounded,
        color: Color(0xFFFFFFFF),
      ),
      onPressed: () => Get.back(),
    ),
    centerTitle: true,
    title: SvgPicture.asset(
      "assets/logo.svg",
      color: const Color(0xFFFFFFFF),
      height: 25,
      width: 30,
    ),
    elevation: 0,
  ),
  extendBodyBehindAppBar: true,
  body: Obx(() {
    if (controller.cameraController.value == null || !controller.cameraController.value!.value.isInitialized) {
      return const Center(child: CircularProgressIndicator());
    }

    return Stack(
      children: [
        CameraPreview(controller.cameraController.value!),
        Positioned(
          bottom: 20,
          left: 20,
          right: 20,
          child: Column(
            children: [
              LinearProgressIndicator(value: controller.progressPercentage.value / 100),
              const SizedBox(height: 20),
              controller.isCapturing.value
                  ? const Text('Capturing... Move the camera along the guidance line.')
                  : IconButton(
                onPressed: controller.startCapturing,
                icon: const Icon(Icons.camera),
              ),
            ],
          ),
        ),
        // Guidance line for panorama capturing
        Positioned(
          top: MediaQuery.of(context).size.height / 2,
          left: 0,
          right: 0,
          child: Container(
            height: 2,
            color: Colors.red,
          ),
        ),
      ],
    );
  }),
);

} }

rainyl commented 3 months ago

A repoducible example please, e.g., a link to github repo, I do not want to copy from here to there, guess what plugins you are used and add the dependencies one by one.

rainyl commented 3 months ago

Allright, reproduced in the example app of abdelaziz-mahdy , refer to https://github.com/tensorflow/tensorflow/issues/48001#issuecomment-1386958937

Add the following lines to section in android/app/src/main/AndroidManifest.xml

<uses-library android:name="libOpenCL.so" android:required="false"/>
<uses-library android:name="libOpenCL-pixel.so" android:required="false"/>
GoxeeVladan commented 3 months ago

thanks, but now when i applied this i get the following error:

E/cv::error()(15188): OpenCV(4.10.0) Error: Requested object was not found (could not open directory: /data/app/~~bJrI2Zx43VlRNHN1PxjXow==/com.goxeedealer.intel_booth_app-qBA-5dV0TeF4sHiSKwsWpA==/base.apk!/lib/arm64-v8a) in glob_rec, file /home/runner/work/opencv.full/opencv.full/build/opencv/modules/core/src/glob.cpp, line 279

but after a minute or so it actually outputs the image, probably need some optimization on my end

dirablue commented 3 months ago

I face the same issue with this with Google Pixel 7 https://github.com/rainyl/opencv_dart/issues/179#issuecomment-2255852537

do you have any idea?


in my case, These are not needed and worked

<uses-library android:name="libOpenCL.so" android:required="false"/>
<uses-library android:name="libOpenCL-pixel.so" android:required="false"/>
rainyl commented 3 months ago

Again, a minimal reproducable example please.

rainyl commented 3 months ago

No response for a long time, I am going to close this issue.

Actually, any exceptions/errors, especially threw by native library, are almost likely to be the result of the users' incorrect usage or the bug of opencv itself, I recommend you search the error message first and then open an issue here.