Skip to content

Commit

Permalink
add contrib:wechat_qrcode
Browse files Browse the repository at this point in the history
  • Loading branch information
rainyl committed Apr 17, 2024
1 parent f644870 commit 7668d0a
Show file tree
Hide file tree
Showing 10 changed files with 357 additions and 1 deletion.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ set(OpenCV_LIBS
opencv_aruco opencv_core opencv_calib3d opencv_dnn opencv_highgui
opencv_features2d opencv_gapi opencv_photo opencv_imgproc
opencv_objdetect opencv_video opencv_videoio opencv_stitching
opencv_img_hash
opencv_img_hash opencv_wechat_qrcode
)

if(ANDROID)
Expand Down
2 changes: 2 additions & 0 deletions ffigen.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ headers:
- src/dnn/dnn.h
- src/extra/aruco.h
- src/extra/img_hash.h
- src/extra/wechat_qrcode.h
- src/features2d/features2d.h
- src/highgui/highgui.h
- src/imgcodecs/imgcodecs.h
Expand All @@ -44,6 +45,7 @@ headers:
- src/dnn/dnn.h
- src/extra/aruco.h
- src/extra/img_hash.h
- src/extra/wechat_qrcode.h
- src/features2d/features2d.h
- src/highgui/highgui.h
- src/imgcodecs/imgcodecs.h
Expand Down
87 changes: 87 additions & 0 deletions lib/src/contrib/wechat_qrcode.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
library cv;

import 'dart:ffi' as ffi;

import 'package:ffi/ffi.dart';

import '../core/base.dart';
import '../core/mat.dart';
import '../core/vec.dart';
import '../opencv.g.dart' as cvg;

class WeChatQRCode extends CvStruct<cvg.WeChatQRCode> {
WeChatQRCode._(super.ptr) : super.fromPointer() {
finalizer.attach(this, ptr.cast());
}

factory WeChatQRCode.empty() {
final p = calloc<cvg.WeChatQRCode>();
cvRun(() => CFFI.WeChatQRCode_New(p));
return WeChatQRCode._(p);
}

/// Initialize the WeChatQRCode.
/// It includes two models, which are packaged with caffe format.
/// Therefore, there are prototxt and caffe models (In total, four paramenters).
///
/// https://docs.opencv.org/4.x/d5/d04/classcv_1_1wechat__qrcode_1_1WeChatQRCode.html#a9c0dc4c37646a1a051340d6b0916f388
factory WeChatQRCode([
String detectorPrototxtPath = "",
String detectorCaffeModelPath = "",
String superResolutionPrototxtPath = "",
String superResolutionCaffeModelPath = "",
]) {
return cvRunArena<WeChatQRCode>((arena) {
final p = calloc<cvg.WeChatQRCode>();
final dp = detectorPrototxtPath.toNativeUtf8(allocator: arena).cast<ffi.Char>();
final dm = detectorCaffeModelPath.toNativeUtf8(allocator: arena).cast<ffi.Char>();
final srp = superResolutionPrototxtPath.toNativeUtf8(allocator: arena).cast<ffi.Char>();
final srm = superResolutionCaffeModelPath.toNativeUtf8(allocator: arena).cast<ffi.Char>();
cvRun(() => CFFI.WeChatQRCode_NewWithParams(dp, dm, srp, srm, p));
return WeChatQRCode._(p);
});
}

/// Both detects and decodes QR code. To simplify the usage, there is a only API: detectAndDecode.
/// https://docs.opencv.org/4.x/d5/d04/classcv_1_1wechat__qrcode_1_1WeChatQRCode.html#a27c167d2d58e5ee4418fd3a9ed5876cc
(List<String>, VecMat points) detectAndDecode(InputArray img, [VecMat? points]) {
final p = calloc<cvg.VecMat>();
final rval = calloc<cvg.VecVecChar>();
cvRun(() => CFFI.WeChatQRCode_DetectAndDecode(ptr, img.ref, p, rval));
final vec = VecVecChar.fromPointer(rval);
final points = VecMat.fromPointer(p);
return (vec.asStringList(), points);
}

/// https://docs.opencv.org/4.x/d5/d04/classcv_1_1wechat__qrcode_1_1WeChatQRCode.html#abf807138abc2626c159abd3e9a80e791
double get scaleFactor {
return cvRunArena<double>((arena) {
final p = calloc<ffi.Float>();
cvRun(() => CFFI.WeChatQRCode_GetScaleFactor(ptr, p));
return p.value;
});
}

/// set scale factor QR code detector use neural network to detect QR.
/// Before running the neural network, the input image is pre-processed by scaling.
/// By default, the input image is scaled to an image with an area of 160000 pixels.
/// The scale factor allows to use custom scale the input image:
/// width = scaleFactor*width height = scaleFactor*width
///
/// scaleFactor valuse must be > 0 and <= 1,
/// otherwise the scaleFactor value is set to -1 and
/// use default scaled to an image with an area of 160000 pixels.
///
/// https://docs.opencv.org/4.x/d5/d04/classcv_1_1wechat__qrcode_1_1WeChatQRCode.html#a084f9aa8693fa0a62c43dd10d2533ab8
set scaleFactor(double scaleFactor) {
cvRun(() => CFFI.WeChatQRCode_SetScaleFactor(ptr, scaleFactor));
}

static final finalizer = OcvFinalizer<cvg.WeChatQRCodePtr>(CFFI.addresses.WeChatQRCode_Close);

@override
List<int> get props => [ptr.address];

@override
cvg.WeChatQRCode get ref => ptr.ref;
}
1 change: 1 addition & 0 deletions lib/src/opencv.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export 'constants.g.dart';
export 'contrib/aruco.dart';
export 'contrib/aruco_dict.dart';
export 'contrib/img_hash.dart';
export 'contrib/wechat_qrcode.dart';

export 'core/array.dart';
export 'core/asyncarray.dart';
Expand Down
135 changes: 135 additions & 0 deletions lib/src/opencv.g.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15867,6 +15867,126 @@ class CvNative {
late final _Watershed =
_WatershedPtr.asFunction<CvStatus Function(Mat, Mat)>();

void WeChatQRCode_Close(
ffi.Pointer<WeChatQRCode> self,
) {
return _WeChatQRCode_Close(
self,
);
}

late final _WeChatQRCode_ClosePtr =
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<WeChatQRCode>)>>(
'WeChatQRCode_Close');
late final _WeChatQRCode_Close = _WeChatQRCode_ClosePtr.asFunction<
void Function(ffi.Pointer<WeChatQRCode>)>();

CvStatus WeChatQRCode_DetectAndDecode(
ffi.Pointer<WeChatQRCode> self,
Mat img,
ffi.Pointer<VecMat> points,
ffi.Pointer<VecVecChar> rval,
) {
return _WeChatQRCode_DetectAndDecode(
self,
img,
points,
rval,
);
}

late final _WeChatQRCode_DetectAndDecodePtr = _lookup<
ffi.NativeFunction<
CvStatus Function(ffi.Pointer<WeChatQRCode>, Mat, ffi.Pointer<VecMat>,
ffi.Pointer<VecVecChar>)>>('WeChatQRCode_DetectAndDecode');
late final _WeChatQRCode_DetectAndDecode =
_WeChatQRCode_DetectAndDecodePtr.asFunction<
CvStatus Function(ffi.Pointer<WeChatQRCode>, Mat, ffi.Pointer<VecMat>,
ffi.Pointer<VecVecChar>)>();

CvStatus WeChatQRCode_GetScaleFactor(
ffi.Pointer<WeChatQRCode> self,
ffi.Pointer<ffi.Float> rval,
) {
return _WeChatQRCode_GetScaleFactor(
self,
rval,
);
}

late final _WeChatQRCode_GetScaleFactorPtr = _lookup<
ffi.NativeFunction<
CvStatus Function(ffi.Pointer<WeChatQRCode>,
ffi.Pointer<ffi.Float>)>>('WeChatQRCode_GetScaleFactor');
late final _WeChatQRCode_GetScaleFactor =
_WeChatQRCode_GetScaleFactorPtr.asFunction<
CvStatus Function(
ffi.Pointer<WeChatQRCode>, ffi.Pointer<ffi.Float>)>();

CvStatus WeChatQRCode_New(
ffi.Pointer<WeChatQRCode> qrcode,
) {
return _WeChatQRCode_New(
qrcode,
);
}

late final _WeChatQRCode_NewPtr =
_lookup<ffi.NativeFunction<CvStatus Function(ffi.Pointer<WeChatQRCode>)>>(
'WeChatQRCode_New');
late final _WeChatQRCode_New = _WeChatQRCode_NewPtr.asFunction<
CvStatus Function(ffi.Pointer<WeChatQRCode>)>();

CvStatus WeChatQRCode_NewWithParams(
ffi.Pointer<ffi.Char> detector_prototxt_path,
ffi.Pointer<ffi.Char> detector_caffe_model_path,
ffi.Pointer<ffi.Char> super_resolution_prototxt_path,
ffi.Pointer<ffi.Char> super_resolution_caffe_model_path,
ffi.Pointer<WeChatQRCode> qrcode,
) {
return _WeChatQRCode_NewWithParams(
detector_prototxt_path,
detector_caffe_model_path,
super_resolution_prototxt_path,
super_resolution_caffe_model_path,
qrcode,
);
}

late final _WeChatQRCode_NewWithParamsPtr = _lookup<
ffi.NativeFunction<
CvStatus Function(
ffi.Pointer<ffi.Char>,
ffi.Pointer<ffi.Char>,
ffi.Pointer<ffi.Char>,
ffi.Pointer<ffi.Char>,
ffi.Pointer<WeChatQRCode>)>>('WeChatQRCode_NewWithParams');
late final _WeChatQRCode_NewWithParams =
_WeChatQRCode_NewWithParamsPtr.asFunction<
CvStatus Function(
ffi.Pointer<ffi.Char>,
ffi.Pointer<ffi.Char>,
ffi.Pointer<ffi.Char>,
ffi.Pointer<ffi.Char>,
ffi.Pointer<WeChatQRCode>)>();

CvStatus WeChatQRCode_SetScaleFactor(
ffi.Pointer<WeChatQRCode> self,
double scale_factor,
) {
return _WeChatQRCode_SetScaleFactor(
self,
scale_factor,
);
}

late final _WeChatQRCode_SetScaleFactorPtr = _lookup<
ffi.NativeFunction<
CvStatus Function(ffi.Pointer<WeChatQRCode>,
ffi.Float)>>('WeChatQRCode_SetScaleFactor');
late final _WeChatQRCode_SetScaleFactor = _WeChatQRCode_SetScaleFactorPtr
.asFunction<CvStatus Function(ffi.Pointer<WeChatQRCode>, double)>();

void Window_Close(
ffi.Pointer<ffi.Char> winname,
) {
Expand Down Expand Up @@ -16513,6 +16633,8 @@ class _SymbolAddresses {
get VideoCapture_Close => _library._VideoCapture_ClosePtr;
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<VideoWriter>)>>
get VideoWriter_Close => _library._VideoWriter_ClosePtr;
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<WeChatQRCode>)>>
get WeChatQRCode_Close => _library._WeChatQRCode_ClosePtr;
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Char>)>>
get Window_Close => _library._Window_ClosePtr;
}
Expand Down Expand Up @@ -17205,6 +17327,13 @@ final class NO_USE_VideoWriterPtr extends ffi.Struct {
external ffi.Pointer<VideoWriterPtr> p;
}

/// \
/// Dart ffigen will not generate typedefs if not referred \
/// so here we confirm they are included \
final class NO_USE_WeChatQRCodePtr extends ffi.Struct {
external ffi.Pointer<WeChatQRCodePtr> p;
}

final class Net extends ffi.Struct {
external ffi.Pointer<ffi.Void> ptr;
}
Expand Down Expand Up @@ -17836,6 +17965,12 @@ final class VideoWriter extends ffi.Struct {
}

typedef VideoWriterPtr = ffi.Pointer<VideoWriter>;

final class WeChatQRCode extends ffi.Struct {
external ffi.Pointer<ffi.Void> ptr;
}

typedef WeChatQRCodePtr = ffi.Pointer<WeChatQRCode>;
typedef double_t = ffi.Double;
typedef Dartdouble_t = double;
typedef float_t = ffi.Float;
Expand Down
56 changes: 56 additions & 0 deletions src/extra/wechat_qrcode.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#include "wechat_qrcode.h"
#include <vector>

CvStatus WeChatQRCode_New(WeChatQRCode *qrcode)
{
BEGIN_WRAP
*qrcode = {new cv::wechat_qrcode::WeChatQRCode()};
END_WRAP
}
CvStatus WeChatQRCode_NewWithParams(const char *detector_prototxt_path, const char *detector_caffe_model_path,
const char *super_resolution_prototxt_path,
const char *super_resolution_caffe_model_path, WeChatQRCode *qrcode)
{
BEGIN_WRAP
*qrcode = {new cv::wechat_qrcode::WeChatQRCode(detector_prototxt_path, detector_caffe_model_path,
super_resolution_prototxt_path,
super_resolution_caffe_model_path)};
END_WRAP
}
void WeChatQRCode_Close(WeChatQRCode *self)
{
delete self->ptr;
self->ptr = nullptr;
delete self;
self = nullptr;
}
CvStatus WeChatQRCode_DetectAndDecode(WeChatQRCode *self, Mat img, VecMat *points, VecVecChar *rval)
{
BEGIN_WRAP
std::vector<cv::Mat> pts;

auto strings = self->ptr->detectAndDecode(*img.ptr, pts);
*points = {new std::vector<cv::Mat>(pts)};

auto cstrings = new std::vector<std::vector<char>>();
cstrings->reserve(strings.size());
for (int i = 0; i < strings.size(); i++) {
auto s = strings.at(i);
cstrings->push_back(std::vector<char>(s.begin(), s.end()));
}
*rval = {cstrings};

END_WRAP
}
CvStatus WeChatQRCode_GetScaleFactor(WeChatQRCode *self, float *rval)
{
BEGIN_WRAP
*rval = self->ptr->getScaleFactor();
END_WRAP
}
CvStatus WeChatQRCode_SetScaleFactor(WeChatQRCode *self, float scale_factor)
{
BEGIN_WRAP
self->ptr->setScaleFactor(scale_factor);
END_WRAP
}
41 changes: 41 additions & 0 deletions src/extra/wechat_qrcode.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
Created by Rainyl.
Licensed: Apache 2.0 license. Copyright (c) 2024 Rainyl.
*/
#pragma once
#ifndef WECHAT_QRCODE_H
#define WECHAT_QRCODE_H

#include "core/core.h"

#ifdef __cplusplus
#include <opencv2/opencv.hpp>
#include <opencv2/wechat_qrcode.hpp>
extern "C" {
#endif

// Main Content Start
#ifdef __cplusplus
CVD_TYPEDEF(cv::wechat_qrcode::WeChatQRCode, WeChatQRCode)
#else
CVD_TYPEDEF(void, WeChatQRCode)
#endif

CVD_TYPEDEF_PTR(WeChatQRCode)

CvStatus WeChatQRCode_New(WeChatQRCode *qrcode);
CvStatus WeChatQRCode_NewWithParams(const char *detector_prototxt_path, const char *detector_caffe_model_path,
const char *super_resolution_prototxt_path,
const char *super_resolution_caffe_model_path, WeChatQRCode *qrcode);
void WeChatQRCode_Close(WeChatQRCode *self);
CvStatus WeChatQRCode_DetectAndDecode(WeChatQRCode *self, Mat img, VecMat *points, VecVecChar *rval);
CvStatus WeChatQRCode_GetScaleFactor(WeChatQRCode *self, float *rval);
CvStatus WeChatQRCode_SetScaleFactor(WeChatQRCode *self, float scale_factor);

// Main Content End

#ifdef __cplusplus
}
#endif

#endif
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit 7668d0a

Please sign in to comment.