From bb36c0b38fcb9b2804766cd8738a862875ac2212 Mon Sep 17 00:00:00 2001 From: Thomas Coldwell <31568400+thomas-coldwell@users.noreply.github.com> Date: Thu, 12 Sep 2024 10:00:29 +0100 Subject: [PATCH 1/4] fix: initial camera passthrough setup --- .../project.pbxproj | 4 +- example/ios/Podfile.lock | 38 +++- example/package.json | 4 + example/src/App.tsx | 38 +++- example/src/examples/CameraPassthrough.tsx | 199 ++++++++++++++++++ .../CameraRealtimeDetection.tsx} | 2 +- example/src/{ => examples}/ImageExample.tsx | 8 +- example/src/home/Home.tsx | 42 ++++ example/src/home/Item.tsx | 56 +++++ example/src/types.ts | 22 ++ yarn.lock | 171 ++++++++++++++- 11 files changed, 566 insertions(+), 18 deletions(-) create mode 100644 example/src/examples/CameraPassthrough.tsx rename example/src/{VisionCameraExample.tsx => examples/CameraRealtimeDetection.tsx} (98%) rename example/src/{ => examples}/ImageExample.tsx (92%) create mode 100644 example/src/home/Home.tsx create mode 100644 example/src/home/Item.tsx create mode 100644 example/src/types.ts diff --git a/example/ios/FastOpencvExample.xcodeproj/project.pbxproj b/example/ios/FastOpencvExample.xcodeproj/project.pbxproj index 38614c1..1221408 100644 --- a/example/ios/FastOpencvExample.xcodeproj/project.pbxproj +++ b/example/ios/FastOpencvExample.xcodeproj/project.pbxproj @@ -472,7 +472,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = PCT6GL3GWD; + DEVELOPMENT_TEAM = TFP6882UUN; ENABLE_BITCODE = NO; INFOPLIST_FILE = FastOpencvExample/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -500,7 +500,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = PCT6GL3GWD; + DEVELOPMENT_TEAM = TFP6882UUN; INFOPLIST_FILE = FastOpencvExample/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 9679ba0..501015e 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -936,7 +936,7 @@ PODS: - React-Mapbuffer (0.74.4): - glog - React-debug - - react-native-fast-opencv (0.2.0): + - react-native-fast-opencv (0.2.4): - DoubleConversion - glog - hermes-engine @@ -979,6 +979,8 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga + - react-native-safe-area-context (4.11.0): + - React-Core - react-native-skia (1.3.11): - DoubleConversion - glog @@ -1300,6 +1302,28 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga + - RNScreens (3.34.0): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Codegen + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-RCTImage + - React-rendererdebug + - React-utils + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga - SocketRocket (0.7.0) - vision-camera-resize-plugin (3.1.0): - DoubleConversion @@ -1372,6 +1396,7 @@ DEPENDENCIES: - React-Mapbuffer (from `../node_modules/react-native/ReactCommon`) - react-native-fast-opencv (from `../..`) - react-native-image-picker (from `../node_modules/react-native-image-picker`) + - react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`) - "react-native-skia (from `../node_modules/@shopify/react-native-skia`)" - react-native-worklets-core (from `../node_modules/react-native-worklets-core`) - React-nativeconfig (from `../node_modules/react-native/ReactCommon`) @@ -1398,6 +1423,7 @@ DEPENDENCIES: - React-utils (from `../node_modules/react-native/ReactCommon/react/utils`) - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) - RNReanimated (from `../node_modules/react-native-reanimated`) + - RNScreens (from `../node_modules/react-native-screens`) - vision-camera-resize-plugin (from `../node_modules/vision-camera-resize-plugin`) - VisionCamera (from `../node_modules/react-native-vision-camera`) - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) @@ -1473,6 +1499,8 @@ EXTERNAL SOURCES: :path: "../.." react-native-image-picker: :path: "../node_modules/react-native-image-picker" + react-native-safe-area-context: + :path: "../node_modules/react-native-safe-area-context" react-native-skia: :path: "../node_modules/@shopify/react-native-skia" react-native-worklets-core: @@ -1525,6 +1553,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon" RNReanimated: :path: "../node_modules/react-native-reanimated" + RNScreens: + :path: "../node_modules/react-native-screens" vision-camera-resize-plugin: :path: "../node_modules/vision-camera-resize-plugin" VisionCamera: @@ -1564,8 +1594,9 @@ SPEC CHECKSUMS: React-jsitracing: 4e9c99e73a6269b27b0d4cbab277dd90df3e5ac0 React-logger: fbfb50e2a2b1b46ee087f0a52739fadecc5e81a4 React-Mapbuffer: d39610dff659d8cf1fea485abae08bbf6f9c8279 - react-native-fast-opencv: d143740f4a4f50a0946a00fbc7e8069ea5427695 + react-native-fast-opencv: 52cb988f5dee40a599381c4617b8560977ed983c react-native-image-picker: c3afe5472ef870d98a4b28415fc0b928161ee5f7 + react-native-safe-area-context: 851c62c48dce80ccaa5637b6aa5991a1bc36eca9 react-native-skia: 8da84ea9410504bf27f0db229539a43f6caabb6a react-native-worklets-core: f51430dd07bf5343d4918d28a4bb00fe8f98b982 React-nativeconfig: 2be4363c2c4ac2b42419577774e83e4e4fd2af9f @@ -1592,10 +1623,11 @@ SPEC CHECKSUMS: React-utils: e8b0eac797c81c574b24f6515fec4015599b643c ReactCommon: eebffb37a90138c6db6eb8b2d952e7e5c6bc083c RNReanimated: 45553a3ae29a75a76269595f8554d07d4090e392 + RNScreens: aa943ad421c3ced3ef5a47ede02b0cbfc43a012e SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d vision-camera-resize-plugin: 4306d5df9bce0e603bbe6ab04337f21a606f4ad1 VisionCamera: 057aff621f7801b7d99a00d157fa39244bbd4fd2 - Yoga: 6259f968a4fdf516d76a4432dead624d71aa0fb1 + Yoga: 0efb3e1bd40ba59b009f01badea863281101de78 PODFILE CHECKSUM: ded8a41f26047703e900afe99b8a72ca375b02ca diff --git a/example/package.json b/example/package.json index 83be1d4..d536ff2 100644 --- a/example/package.json +++ b/example/package.json @@ -10,11 +10,15 @@ "build:ios": "react-native build-ios --scheme FastOpencvExample --mode Debug --extra-params \"-sdk iphonesimulator CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ GCC_OPTIMIZATION_LEVEL=0 GCC_PRECOMPILE_PREFIX_HEADER=YES ASSETCATALOG_COMPILER_OPTIMIZATION=time DEBUG_INFORMATION_FORMAT=dwarf COMPILER_INDEX_STORE_ENABLE=NO\"" }, "dependencies": { + "@react-navigation/native": "^6.1.18", + "@react-navigation/native-stack": "^6.11.0", "@shopify/react-native-skia": "^1.3.10", "react": "18.2.0", "react-native": "0.74.4", "react-native-image-picker": "^7.1.2", "react-native-reanimated": "^3.14.0", + "react-native-safe-area-context": "^4.11.0", + "react-native-screens": "^3.34.0", "react-native-vision-camera": "^4.5.2", "react-native-worklets-core": "^1.3.3", "vision-camera-resize-plugin": "^3.1.0" diff --git a/example/src/App.tsx b/example/src/App.tsx index 7d2d357..5fcf0dc 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -1,12 +1,32 @@ -import { ImageExample } from './ImageExample'; -import { VisionCameraExample } from './VisionCameraExample'; +import { ImageExample } from './examples/ImageExample'; +import { Route, type StackParamList } from './types'; +import { CameraRealtimeDetection } from './examples/CameraRealtimeDetection'; +import { NavigationContainer } from '@react-navigation/native'; +import { createNativeStackNavigator } from '@react-navigation/native-stack'; +import { Home } from './home/Home'; +import { CameraPassthrough } from './examples/CameraPassthrough'; -export default function App() { - const camera = false; - - if (camera) { - return ; - } +const Stack = createNativeStackNavigator(); - return ; +export default function App() { + return ( + + + + + + + + + ); } diff --git a/example/src/examples/CameraPassthrough.tsx b/example/src/examples/CameraPassthrough.tsx new file mode 100644 index 0000000..8f4e9d2 --- /dev/null +++ b/example/src/examples/CameraPassthrough.tsx @@ -0,0 +1,199 @@ +import { + AlphaType, + Canvas, + ColorType, + Image, + Skia, + type SkData, + type SkImage, +} from '@shopify/react-native-skia'; +import { useEffect } from 'react'; +import { SafeAreaView, StyleSheet, Text, View } from 'react-native'; +import { OpenCV } from 'react-native-fast-opencv'; +import { useSharedValue } from 'react-native-reanimated'; +import { + Camera, + useCameraDevice, + useCameraPermission, + useFrameProcessor, +} from 'react-native-vision-camera'; +import { useRunOnJS } from 'react-native-worklets-core'; +import { useResizePlugin, type Options } from 'vision-camera-resize-plugin'; + +type PixelFormat = Options<'uint8'>['pixelFormat']; + +const WIDTH = 300; +const HEIGHT = 300; +const TARGET_TYPE = 'uint8' as const; +const TARGET_FORMAT: PixelFormat = 'rgba'; + +let lastWarn: PixelFormat | undefined; +lastWarn = undefined; +function warnNotSupported(pixelFormat: PixelFormat) { + if (lastWarn !== pixelFormat) { + console.log( + `Pixel Format '${pixelFormat}' is not natively supported by Skia! ` + + `Displaying a fall-back format that might use wrong colors instead...` + ); + lastWarn = pixelFormat; + } +} + +function getSkiaTypeForPixelFormat(pixelFormat: PixelFormat): ColorType { + switch (pixelFormat) { + case 'abgr': + case 'argb': + warnNotSupported(pixelFormat); + return ColorType.RGBA_8888; + case 'bgr': + warnNotSupported(pixelFormat); + return ColorType.RGB_888x; + case 'rgb': + return ColorType.RGB_888x; + case 'rgba': + return ColorType.RGBA_8888; + case 'bgra': + return ColorType.BGRA_8888; + } +} +function getComponentsPerPixel(pixelFormat: PixelFormat): number { + switch (pixelFormat) { + case 'abgr': + case 'rgba': + case 'bgra': + case 'argb': + return 4; + case 'rgb': + case 'bgr': + return 3; + } +} + +export function createSkiaImageFromData( + data: SkData, + width: number, + height: number, + pixelFormat: PixelFormat +): SkImage | null { + const componentsPerPixel = getComponentsPerPixel(pixelFormat); + return Skia.Image.MakeImage( + { + width: width, + height: height, + alphaType: AlphaType.Opaque, + colorType: getSkiaTypeForPixelFormat(pixelFormat), + }, + data, + width * componentsPerPixel + ); +} + +export function CameraPassthrough() { + const device = useCameraDevice('back'); + const { hasPermission, requestPermission } = useCameraPermission(); + const previewImage = useSharedValue(null); + const { resize } = useResizePlugin(); + + useEffect(() => { + requestPermission(); + }, [requestPermission]); + + const updatePreviewImageFromData = useRunOnJS( + (data: SkData, pixelFormat: PixelFormat) => { + const image = createSkiaImageFromData(data, WIDTH, HEIGHT, pixelFormat); + if (image == null) { + throw new Error('Failed to create Skia image from data'); + } + previewImage.value?.dispose(); + previewImage.value = image; + }, + [] + ); + + const frameProcessor = useFrameProcessor( + (frame) => { + 'worklet'; + + const resized = resize(frame, { + scale: { + width: WIDTH, + height: HEIGHT, + }, + crop: { + x: 0, + y: 0, + width: frame.width, + height: frame.height, + }, + pixelFormat: TARGET_FORMAT, + dataType: TARGET_TYPE, + rotation: '90deg', + }); + + // const frameMat = OpenCV.frameBufferToMat(HEIGHT, WIDTH, resized); + // const output = OpenCV.matToBuffer(frameMat, 'uint8'); + const data = Skia.Data.fromBytes(resized); + + updatePreviewImageFromData(data, TARGET_FORMAT).then(() => { + data.dispose(); + }); + + OpenCV.clearBuffers(); // REMEMBER TO CLEAN + }, + [updatePreviewImageFromData] + ); + + if (!hasPermission) { + return No permission; + } + + if (device == null) { + return No device; + } + + return ( + + + + + + + + + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + width: '100%', + alignItems: 'center', + justifyContent: 'center', + }, + safe: { + flex: 1, + width: '100%', + alignItems: 'center', + justifyContent: 'flex-end', + }, + canvas: { + width: WIDTH, + height: HEIGHT, + borderColor: 'red', + borderWidth: 2, + }, +}); diff --git a/example/src/VisionCameraExample.tsx b/example/src/examples/CameraRealtimeDetection.tsx similarity index 98% rename from example/src/VisionCameraExample.tsx rename to example/src/examples/CameraRealtimeDetection.tsx index d09d946..e99750a 100644 --- a/example/src/VisionCameraExample.tsx +++ b/example/src/examples/CameraRealtimeDetection.tsx @@ -22,7 +22,7 @@ const paint = Skia.Paint(); paint.setStyle(PaintStyle.Fill); paint.setColor(Skia.Color('red')); -export function VisionCameraExample() { +export function CameraRealtimeDetection() { const device = useCameraDevice('back'); const { hasPermission, requestPermission } = useCameraPermission(); diff --git a/example/src/ImageExample.tsx b/example/src/examples/ImageExample.tsx similarity index 92% rename from example/src/ImageExample.tsx rename to example/src/examples/ImageExample.tsx index 908a96e..63dc287 100644 --- a/example/src/ImageExample.tsx +++ b/example/src/examples/ImageExample.tsx @@ -1,9 +1,13 @@ import { useState } from 'react'; import { Button, Image, SafeAreaView } from 'react-native'; -import { DataTypes, ObjectType, OpenCV } from 'react-native-fast-opencv'; +import { + DataTypes, + ObjectType, + OpenCV, + BorderTypes, +} from 'react-native-fast-opencv'; import { launchImageLibrary, type Asset } from 'react-native-image-picker'; import { useRunOnJS, useWorklet } from 'react-native-worklets-core'; -import { BorderTypes } from '../../src/constants/Core'; export function ImageExample() { const [photo, setPhoto] = useState(null); diff --git a/example/src/home/Home.tsx b/example/src/home/Home.tsx new file mode 100644 index 0000000..e3e41c7 --- /dev/null +++ b/example/src/home/Home.tsx @@ -0,0 +1,42 @@ +import { ScrollView } from 'react-native'; +import { Route } from '../types'; +import { Item } from './Item'; + +interface ItemDetails { + title: string; + emoji: string; + description: string; + route: Route; + testId?: string; +} + +const items: ItemDetails[] = [ + { + title: 'Image Blur', + emoji: '🔍', + description: 'Blur an image', + route: Route.ImageBlur, + }, + { + title: 'Camera Passthrough', + emoji: '📷', + description: 'Pass camera feed through', + route: Route.CameraPassthrough, + }, + { + title: 'Camera Realtime Detection', + emoji: '📷', + description: 'Detect objects in realtime', + route: Route.CameraRealtimeDetection, + }, +]; + +export const Home = () => { + return ( + + {items.map((item, index) => ( + + ))} + + ); +}; diff --git a/example/src/home/Item.tsx b/example/src/home/Item.tsx new file mode 100644 index 0000000..a333569 --- /dev/null +++ b/example/src/home/Item.tsx @@ -0,0 +1,56 @@ +import { useNavigation } from '@react-navigation/native'; +import { useCallback } from 'react'; +import { TouchableOpacity, View, Text, StyleSheet } from 'react-native'; +import type { Route } from '../types'; + +interface ItemProps { + title: string; + emoji: string; + description: string; + route: Route; + testId?: string; +} + +export const Item = (props: ItemProps) => { + const { title, emoji, description, route, testId } = props; + const navigation = useNavigation(); + const gotoRoute = useCallback(() => { + navigation.navigate(route); + }, [route, navigation]); + + return ( + + + + {title} {emoji} + + {description} + + 👉 + + ); +}; + +const styles = StyleSheet.create({ + container: { + backgroundColor: '#FFFFFF', + padding: 16, + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + borderBottomColor: '#CCC', + borderBottomWidth: 1, + }, + title: { + fontWeight: 'bold', + paddingBottom: 4, + color: 'black', + }, + description: { + color: 'black', + }, +}); diff --git a/example/src/types.ts b/example/src/types.ts new file mode 100644 index 0000000..f9229e4 --- /dev/null +++ b/example/src/types.ts @@ -0,0 +1,22 @@ +import type { ParamListBase } from '@react-navigation/native'; + +export enum Route { + Home = 'Home', + ImageBlur = 'ImageBlur', + CameraPassthrough = 'CameraPassthrough', + CameraRealtimeDetection = 'CameraRealtimeDetection', +} + +export interface StackParamList extends ParamListBase { + Home: undefined; + ImageBlur: undefined; + CameraPassthrough: undefined; + CameraRealtimeDetection: undefined; +} + +// https://reactnavigation.org/docs/typescript#specifying-default-types-for-usenavigation-link-ref-etc +declare global { + namespace ReactNavigation { + interface RootParamList extends StackParamList {} + } +} diff --git a/yarn.lock b/yarn.lock index e6babeb..6f336bb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3019,6 +3019,74 @@ __metadata: languageName: node linkType: hard +"@react-navigation/core@npm:^6.4.17": + version: 6.4.17 + resolution: "@react-navigation/core@npm:6.4.17" + dependencies: + "@react-navigation/routers": "npm:^6.1.9" + escape-string-regexp: "npm:^4.0.0" + nanoid: "npm:^3.1.23" + query-string: "npm:^7.1.3" + react-is: "npm:^16.13.0" + use-latest-callback: "npm:^0.2.1" + peerDependencies: + react: "*" + checksum: 10/481470361c7dd638d8af513ca559265829e8de5a2ff18c207d8d1c9e2d65606318061ffe369afbccfea3c6d027d38ad539ae5bae8863d9cedd8eaeafeb18426c + languageName: node + linkType: hard + +"@react-navigation/elements@npm:^1.3.31": + version: 1.3.31 + resolution: "@react-navigation/elements@npm:1.3.31" + peerDependencies: + "@react-navigation/native": ^6.0.0 + react: "*" + react-native: "*" + react-native-safe-area-context: ">= 3.0.0" + checksum: 10/379b3657300f9ab8043979f1ecaea95dce96253903db8d6954468e39dc7cf0710cc08345fa6625071a1505b6442a395e0e20bde39c0b997fd90fea370275fc08 + languageName: node + linkType: hard + +"@react-navigation/native-stack@npm:^6.11.0": + version: 6.11.0 + resolution: "@react-navigation/native-stack@npm:6.11.0" + dependencies: + "@react-navigation/elements": "npm:^1.3.31" + warn-once: "npm:^0.1.0" + peerDependencies: + "@react-navigation/native": ^6.0.0 + react: "*" + react-native: "*" + react-native-safe-area-context: ">= 3.0.0" + react-native-screens: ">= 3.0.0" + checksum: 10/d27212088dde4ca16c78d8f85187d452d56cc9243506c049d2595b61c10eda44368ab01c53e729777d9900fe5c3a4dfeae2598b1a534508d6a1df8ab35c1a4dc + languageName: node + linkType: hard + +"@react-navigation/native@npm:^6.1.18": + version: 6.1.18 + resolution: "@react-navigation/native@npm:6.1.18" + dependencies: + "@react-navigation/core": "npm:^6.4.17" + escape-string-regexp: "npm:^4.0.0" + fast-deep-equal: "npm:^3.1.3" + nanoid: "npm:^3.1.23" + peerDependencies: + react: "*" + react-native: "*" + checksum: 10/1c16813e7d1d796519d0c3a9163de8be6d4af0afa74d9d88ec6729f8c0f533540250f09e39063f4a1eafb9ff71c3f3a9cc9d420ba75aa3eb7f42834f4ba0ee20 + languageName: node + linkType: hard + +"@react-navigation/routers@npm:^6.1.9": + version: 6.1.9 + resolution: "@react-navigation/routers@npm:6.1.9" + dependencies: + nanoid: "npm:^3.1.23" + checksum: 10/35af21aa89074b6c4ef8e7a52701694cf393eda4bc3b237e8c908b27468a2f14c04acfaf702acfe833713730e65cac31733e411a3bdf459859e9b1c823d0c06e + languageName: node + linkType: hard + "@release-it/conventional-changelog@npm:^5.0.0": version: 5.1.1 resolution: "@release-it/conventional-changelog@npm:5.1.1" @@ -5243,6 +5311,13 @@ __metadata: languageName: node linkType: hard +"decode-uri-component@npm:^0.2.2": + version: 0.2.2 + resolution: "decode-uri-component@npm:0.2.2" + checksum: 10/17a0e5fa400bf9ea84432226e252aa7b5e72793e16bf80b907c99b46a799aeacc139ec20ea57121e50c7bd875a1a4365928f884e92abf02e21a5a13790a0f33e + languageName: node + linkType: hard + "decompress-response@npm:^6.0.0": version: 6.0.0 resolution: "decompress-response@npm:6.0.0" @@ -6339,6 +6414,13 @@ __metadata: languageName: node linkType: hard +"filter-obj@npm:^1.1.0": + version: 1.1.0 + resolution: "filter-obj@npm:1.1.0" + checksum: 10/9d681939eec2b4b129cb4f307b7e93d954a0657421d4e5357d86093b26d3f4f570909ed43717dcfd62428b3cf8cddd9841b35f9d40d12ac62cfabaa677942593 + languageName: node + linkType: hard + "finalhandler@npm:1.1.2": version: 1.1.2 resolution: "finalhandler@npm:1.1.2" @@ -9737,6 +9819,15 @@ __metadata: languageName: node linkType: hard +"nanoid@npm:^3.1.23": + version: 3.3.7 + resolution: "nanoid@npm:3.3.7" + bin: + nanoid: bin/nanoid.cjs + checksum: 10/ac1eb60f615b272bccb0e2b9cd933720dad30bf9708424f691b8113826bb91aca7e9d14ef5d9415a6ba15c266b37817256f58d8ce980c82b0ba3185352565679 + languageName: node + linkType: hard + "natural-compare-lite@npm:^1.4.0": version: 1.4.0 resolution: "natural-compare-lite@npm:1.4.0" @@ -10722,6 +10813,18 @@ __metadata: languageName: node linkType: hard +"query-string@npm:^7.1.3": + version: 7.1.3 + resolution: "query-string@npm:7.1.3" + dependencies: + decode-uri-component: "npm:^0.2.2" + filter-obj: "npm:^1.1.0" + split-on-first: "npm:^1.0.0" + strict-uri-encode: "npm:^2.0.0" + checksum: 10/3b6f2c167e76ca4094c5f1a9eb276efcbb9ebfd8b1a28c413f3c4e4e7d6428c8187bf46c8cbc9f92a229369dd0015de10a7fd712c8cee98d5d84c2ac6140357e + languageName: node + linkType: hard + "querystring@npm:^0.2.1": version: 0.2.1 resolution: "querystring@npm:0.2.1" @@ -10790,6 +10893,15 @@ __metadata: languageName: node linkType: hard +"react-freeze@npm:^1.0.0": + version: 1.0.4 + resolution: "react-freeze@npm:1.0.4" + peerDependencies: + react: ">=17.0.0" + checksum: 10/1dc433319341ec3dca84513c4197ef4f4c8232604d35f83546a8abfb41d9591f934b66aaaa4dc3dc8b1b65f488705a2a48ae6c1d9792660119a9cdedeab4ca8f + languageName: node + linkType: hard + "react-is@npm:^16.12.0 || ^17.0.0 || ^18.0.0, react-is@npm:^18.0.0": version: 18.3.1 resolution: "react-is@npm:18.3.1" @@ -10797,7 +10909,7 @@ __metadata: languageName: node linkType: hard -"react-is@npm:^16.13.1": +"react-is@npm:^16.13.0, react-is@npm:^16.13.1": version: 16.13.1 resolution: "react-is@npm:16.13.1" checksum: 10/5aa564a1cde7d391ac980bedee21202fc90bdea3b399952117f54fb71a932af1e5902020144fb354b4690b2414a0c7aafe798eb617b76a3d441d956db7726fdf @@ -10853,12 +10965,16 @@ __metadata: "@react-native/babel-preset": "npm:0.74.86" "@react-native/metro-config": "npm:0.74.86" "@react-native/typescript-config": "npm:0.74.86" + "@react-navigation/native": "npm:^6.1.18" + "@react-navigation/native-stack": "npm:^6.11.0" "@shopify/react-native-skia": "npm:^1.3.10" react: "npm:18.2.0" react-native: "npm:0.74.4" react-native-builder-bob: "npm:^0.29.0" react-native-image-picker: "npm:^7.1.2" react-native-reanimated: "npm:^3.14.0" + react-native-safe-area-context: "npm:^4.11.0" + react-native-screens: "npm:^3.34.0" react-native-vision-camera: "npm:^4.5.2" react-native-worklets-core: "npm:^1.3.3" vision-camera-resize-plugin: "npm:^3.1.0" @@ -10946,6 +11062,29 @@ __metadata: languageName: node linkType: hard +"react-native-safe-area-context@npm:^4.11.0": + version: 4.11.0 + resolution: "react-native-safe-area-context@npm:4.11.0" + peerDependencies: + react: "*" + react-native: "*" + checksum: 10/f2e616ad3087ebf1ad34f90f4eadc2d6865d3d56bba83bcfb9d04020b4344d892e347b7f55dcd996c4d2edf21b589a5ce710a52e62a7bd86597ed34d130599b2 + languageName: node + linkType: hard + +"react-native-screens@npm:^3.34.0": + version: 3.34.0 + resolution: "react-native-screens@npm:3.34.0" + dependencies: + react-freeze: "npm:^1.0.0" + warn-once: "npm:^0.1.0" + peerDependencies: + react: "*" + react-native: "*" + checksum: 10/dfcbde7de4aae27980191bc64861190b2edece8f0e3988ef7e83ee6a7895df35fe006024d8fa0611cefc1e7dd6d574ce598f1dcb036750dc6b0a5fca073dd2b9 + languageName: node + linkType: hard + "react-native-vision-camera@npm:^4.5.2": version: 4.5.2 resolution: "react-native-vision-camera@npm:4.5.2" @@ -12036,6 +12175,13 @@ __metadata: languageName: node linkType: hard +"split-on-first@npm:^1.0.0": + version: 1.1.0 + resolution: "split-on-first@npm:1.1.0" + checksum: 10/16ff85b54ddcf17f9147210a4022529b343edbcbea4ce977c8f30e38408b8d6e0f25f92cd35b86a524d4797f455e29ab89eb8db787f3c10708e0b47ebf528d30 + languageName: node + linkType: hard + "split2@npm:^3.0.0, split2@npm:^3.2.2": version: 3.2.2 resolution: "split2@npm:3.2.2" @@ -12123,6 +12269,13 @@ __metadata: languageName: node linkType: hard +"strict-uri-encode@npm:^2.0.0": + version: 2.0.0 + resolution: "strict-uri-encode@npm:2.0.0" + checksum: 10/eaac4cf978b6fbd480f1092cab8b233c9b949bcabfc9b598dd79a758f7243c28765ef7639c876fa72940dac687181b35486ea01ff7df3e65ce3848c64822c581 + languageName: node + linkType: hard + "string-hash-64@npm:^1.0.3": version: 1.0.3 resolution: "string-hash-64@npm:1.0.3" @@ -13081,6 +13234,15 @@ __metadata: languageName: node linkType: hard +"use-latest-callback@npm:^0.2.1": + version: 0.2.1 + resolution: "use-latest-callback@npm:0.2.1" + peerDependencies: + react: ">=16.8" + checksum: 10/da5718eda625738cc7dac8fb502d0f8f2039435eb71203565a72c32e0f5769e7b8ddac074e650066636e7f4b29b45524f751cb18a2b430856d98879bbb10d274 + languageName: node + linkType: hard + "utf8@npm:^3.0.0": version: 3.0.0 resolution: "utf8@npm:3.0.0" @@ -13165,6 +13327,13 @@ __metadata: languageName: node linkType: hard +"warn-once@npm:^0.1.0": + version: 0.1.1 + resolution: "warn-once@npm:0.1.1" + checksum: 10/e6a5a1f5a8dba7744399743d3cfb571db4c3947897875d4962a7c5b1bf2195ab4518c838cb4cea652e71729f21bba2e98dc75686f5fccde0fabbd894e2ed0c0d + languageName: node + linkType: hard + "wcwidth@npm:^1.0.1": version: 1.0.1 resolution: "wcwidth@npm:1.0.1" From 1e0b5ff3d92ed960ec857542ca7787083f4916a7 Mon Sep 17 00:00:00 2001 From: Thomas Coldwell <31568400+thomas-coldwell@users.noreply.github.com> Date: Thu, 12 Sep 2024 10:05:24 +0100 Subject: [PATCH 2/4] fix: try-catch opencv invoke errors --- cpp/FOCV_Function.cpp | 2470 +++++++++++++++++++++-------------------- 1 file changed, 1237 insertions(+), 1233 deletions(-) diff --git a/cpp/FOCV_Function.cpp b/cpp/FOCV_Function.cpp index 1f196b1..53cddea 100644 --- a/cpp/FOCV_Function.cpp +++ b/cpp/FOCV_Function.cpp @@ -19,8 +19,8 @@ constexpr uint64_t hashString(const char* str, size_t length) { const uint64_t fnv_prime = 1099511628211ull; for (size_t i = 0; i < length; ++i) { - hash ^= static_cast(str[i]); - hash *= fnv_prime; + hash ^= static_cast(str[i]); + hash *= fnv_prime; } return hash; @@ -29,1263 +29,1267 @@ constexpr uint64_t hashString(const char* str, size_t length) { // General idea of invocation switch is from react-native-opencv3 library, // but it was adapted and optimized. jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* arguments) { - jsi::Object value(runtime); - - FOCV_FunctionArguments args(runtime, arguments); - - std::string functionName = args.asString(0); - + jsi::Object value(runtime); + + FOCV_FunctionArguments args(runtime, arguments); + + std::string functionName = args.asString(0); + + try { switch (hashString(functionName.c_str(), functionName.size())) { - case hashString("absdiff", 7): { - auto src1 = args.asMatPtr(1); - auto src2 = args.asMatPtr(2); - auto dst = args.asMatPtr(3); - - cv::absdiff(*src1, *src2, *dst); - } break; - case hashString("add", 3): { - auto src1 = args.asMatPtr(1); - auto src2 = args.asMatPtr(2); - auto dst = args.asMatPtr(3); - - if(args.isNumber(5)) { - auto mask = args.asMatPtr(4); - auto dtype = args.asNumber(5); - - cv::add(*src1, *src2, *dst, *mask, dtype); - } else if(args.isObject(4)) { - auto mask = args.asMatPtr(4); - - cv::add(*src1, *src2, *dst, *mask); - } else { - cv::add(*src1, *src2, *dst); - } - } break; - case hashString("addWeighted", 11): { - auto src1 = args.asMatPtr(1); - auto alpha = args.asNumber(2); - auto src2 = args.asMatPtr(3); - auto beta = args.asNumber(4); - auto gamma = args.asNumber(5); - auto dst = args.asMatPtr(6); - - if(args.isNumber(7)) { - auto dtype = args.asNumber(7); - - cv::addWeighted(*src1, alpha, *src2, beta, gamma, *dst, dtype); - } else { - cv::addWeighted(*src1, alpha, *src2, beta, gamma, *dst); - } - } break; - case hashString("batchDistance", 13): { - auto src1 = args.asMatPtr(1); - auto src2 = args.asMatPtr(2); - auto dist = args.asMatPtr(3); - auto dtype = args.asNumber(4); - auto nidx = args.asMatPtr(5); - auto normType = args.asNumber(6); - auto K = args.asNumber(7); - auto mask = args.asMatPtr(8); - auto update = args.asNumber(9); - auto crosscheck = args.asNumber(10); - - cv::batchDistance(*src1, *src2, *dist, dtype, *nidx, normType, K, *mask, update, crosscheck); - } break; - case hashString("bitwise_and", 11): { - auto src1 = args.asMatPtr(1); - auto src2 = args.asMatPtr(2); - auto dst = args.asMatPtr(3); - - if(args.isObject(4)) { - auto mask = args.asMatPtr(4); - - cv::bitwise_and(*src1, *src2, *dst, *mask); - } else { - cv::bitwise_and(*src1, *src2, *dst); - } - } break; - case hashString("bitwise_not", 11): { - auto src1 = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - - if(args.isObject(3)) { - auto mask = args.asMatPtr(3); - - cv::bitwise_not(*src1, *dst, *mask); - } else { - cv::bitwise_not(*src1, *dst); - } - } break; - case hashString("bitwise_or", 10): { - auto src1 = args.asMatPtr(1); - auto src2 = args.asMatPtr(2); - auto dst = args.asMatPtr(3); - - if(args.isObject(4)) { - auto mask = args.asMatPtr(4); - - cv::bitwise_or(*src1, *src2, *dst, *mask); - } else { - cv::bitwise_or(*src1, *src2, *dst); - } - } break; - case hashString("bitwise_xor", 11): { - auto src1 = args.asMatPtr(1); - auto src2 = args.asMatPtr(2); - auto dst = args.asMatPtr(3); - - if(args.isObject(4)) { - auto mask = args.asMatPtr(4); - - cv::bitwise_xor(*src1, *src2, *dst, *mask); - } else { - cv::bitwise_xor(*src1, *src2, *dst); - } - } break; - case hashString("borderInterpolate", 17): { - auto p = args.asNumber(1); - auto len = args.asNumber(2); - auto borderType = args.asNumber(3); - - auto result = cv::borderInterpolate(p, len, borderType); - value.setProperty(runtime, "value", result); - } break; - case hashString("calcCovarMatrix", 15): { - auto samples = args.asMatVectorPtr(1); - auto nsamples = args.asNumber(2); - auto covar = args.asMatPtr(3); - auto mean = args.asMatPtr(4); - auto flags = args.asNumber(5); - auto dtype = args.asNumber(6); - - cv::calcCovarMatrix((*samples).data(), nsamples, *covar, *mean, flags, dtype); - } break; - case hashString("cartToPolar", 11): { - if(args.isMat(1)) { - auto x = args.asMatPtr(1); - auto y = args.asMatPtr(2); - auto magnitude = args.asMatPtr(3); - auto angle = args.asMatPtr(4); - - if(args.isBool(5)) { - auto angleInDegrees = args.asBool(5); - - cv::cartToPolar(*x, *y, *magnitude, *angle, angleInDegrees); - } else { - cv::cartToPolar(*x, *y, *magnitude, *angle); - } - } else { - auto x = args.asMatVectorPtr(1); - auto y = args.asMatVectorPtr(2); - auto magnitude = args.asMatVectorPtr(3); - auto angle = args.asMatVectorPtr(4); - - if(args.isBool(5)) { - auto angleInDegrees = args.asBool(5); - - cv::cartToPolar(*x, *y, *magnitude, *angle, angleInDegrees); - } else { - cv::cartToPolar(*x, *y, *magnitude, *angle); - } - } - } break; - case hashString("checkRange", 10): { - auto quiet = args.asBool(2); - auto pos = args.asPointPtr(3); - auto minVal = args.asNumber(2); - auto maxVal = args.asNumber(2); - - if(args.isMat(1)) { - auto a = args.asMatPtr(1); - cv::checkRange(*a, quiet, &(*pos), minVal, maxVal); - } else { - auto a = args.asMatVectorPtr(1); - cv::checkRange(*a, quiet, &(*pos), minVal, maxVal); - } - } break; - case hashString("compare", 7): { - auto src1 = args.asMatPtr(1); - auto src2 = args.asMatPtr(2); - auto dst = args.asMatPtr(3); - auto cmpop = args.asNumber(4); - - cv::compare(*src1, *src2, *dst, cmpop); - } break; - case hashString("completeSymm", 12): { - auto lowerToUpper = args.asBool(2); - - if(args.isMat(1)) { - auto m = args.asMatPtr(1); - cv::completeSymm(*m, lowerToUpper); - } else { - auto m = args.asMatVectorPtr(1); - cv::completeSymm(*m, lowerToUpper); - } - } break; - case hashString("convertFp16", 11): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - - cv::convertFp16(*src, *dst); - } break; - case hashString("convertScaleAbs", 15): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - - if(args.isNumber(4)) { - auto alpha = args.asNumber(3); - auto beta = args.asNumber(4); - - cv::convertScaleAbs(*src, *dst, alpha, beta); - } else if(args.isNumber(3)) { - auto alpha = args.asNumber(3); - - cv::convertScaleAbs(*src, *dst, alpha); - } else { - cv::convertScaleAbs(*src, *dst); - } - } break; - case hashString("copyMakeBorder", 14): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto top = args.asNumber(3); - auto bottom = args.asNumber(4); - auto left = args.asNumber(5); - auto right = args.asNumber(6); - auto borderType = args.asNumber(7); - auto value = args.asScalarPtr(8); - - cv::copyMakeBorder(*src, *dst, top, bottom, left, right, borderType, *value); - } break; - case hashString("copyTo", 6): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto mask = args.asMatPtr(3); - - cv::copyTo(*src, *dst, *mask); - } break; - case hashString("countNonZero", 12): { - if(args.isMat(1)) { - auto src = args.asMatPtr(1); - auto result = cv::countNonZero(*src); - value.setProperty(runtime, "value", result); - } else { - auto src = args.asMatVectorPtr(1); - auto result = cv::countNonZero(*src); - value.setProperty(runtime, "value", result); - } - } break; - case hashString("dct", 3): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto flags = args.asNumber(3); - - cv::dct(*src, *dst, flags); - } break; - case hashString("determinant", 11): { - auto src = args.asMatPtr(1); - - auto result = cv::determinant(*src); - value.setProperty(runtime, "value", result); - } break; - case hashString("dft", 3): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto flags = args.asNumber(3); - auto nonzeroRows = args.asNumber(4); - - cv::dft(*src, *dst, flags, nonzeroRows); - } break; - case hashString("divide", 6): { - auto src1 = args.asMatPtr(1); - auto src2 = args.asMatPtr(2); - auto dst = args.asMatPtr(3); - auto scale = args.asNumber(4); - - if(args.isNumber(5)) { - auto dtype = args.asNumber(5); - - cv::divide(*src1, *src2, *dst, scale, dtype); - } else { - cv::divide(*src1, *src2, *dst, scale); - } - } break; - case hashString("eigen", 5): { - auto src = args.asMatPtr(1); - auto eigenvalues = args.asMatPtr(2); - auto eigenvectors = args.asMatPtr(3); + case hashString("absdiff", 7): { + auto src1 = args.asMatPtr(1); + auto src2 = args.asMatPtr(2); + auto dst = args.asMatPtr(3); + + cv::absdiff(*src1, *src2, *dst); + } break; + case hashString("add", 3): { + auto src1 = args.asMatPtr(1); + auto src2 = args.asMatPtr(2); + auto dst = args.asMatPtr(3); + + if(args.isNumber(5)) { + auto mask = args.asMatPtr(4); + auto dtype = args.asNumber(5); - cv::eigen(*src, *eigenvalues, *eigenvectors); - } break; - case hashString("eigenNonSymmetric", 17): { - auto src = args.asMatPtr(1); - auto eigenvalues = args.asMatPtr(2); - auto eigenvectors = args.asMatPtr(3); + cv::add(*src1, *src2, *dst, *mask, dtype); + } else if(args.isObject(4)) { + auto mask = args.asMatPtr(4); - cv::eigenNonSymmetric(*src, *eigenvalues, *eigenvectors); - } break; - case hashString("exp", 3): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); + cv::add(*src1, *src2, *dst, *mask); + } else { + cv::add(*src1, *src2, *dst); + } + } break; + case hashString("addWeighted", 11): { + auto src1 = args.asMatPtr(1); + auto alpha = args.asNumber(2); + auto src2 = args.asMatPtr(3); + auto beta = args.asNumber(4); + auto gamma = args.asNumber(5); + auto dst = args.asMatPtr(6); + + if(args.isNumber(7)) { + auto dtype = args.asNumber(7); - cv::exp(*src, *dst); - } break; - case hashString("extractChannel", 14): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto coi = args.asNumber(3); + cv::addWeighted(*src1, alpha, *src2, beta, gamma, *dst, dtype); + } else { + cv::addWeighted(*src1, alpha, *src2, beta, gamma, *dst); + } + } break; + case hashString("batchDistance", 13): { + auto src1 = args.asMatPtr(1); + auto src2 = args.asMatPtr(2); + auto dist = args.asMatPtr(3); + auto dtype = args.asNumber(4); + auto nidx = args.asMatPtr(5); + auto normType = args.asNumber(6); + auto K = args.asNumber(7); + auto mask = args.asMatPtr(8); + auto update = args.asNumber(9); + auto crosscheck = args.asNumber(10); + + cv::batchDistance(*src1, *src2, *dist, dtype, *nidx, normType, K, *mask, update, crosscheck); + } break; + case hashString("bitwise_and", 11): { + auto src1 = args.asMatPtr(1); + auto src2 = args.asMatPtr(2); + auto dst = args.asMatPtr(3); + + if(args.isObject(4)) { + auto mask = args.asMatPtr(4); - cv::extractChannel(*src, *dst, coi); - } break; - case hashString("findNonZero", 11): { - auto src = args.asMatPtr(1); - - if(args.isMat(2)) { - auto idx = args.asMatPtr(2); - cv::findNonZero(*src, *idx); - } else { - auto idx = args.asPointVectorPtr(2); - cv::findNonZero(*src, *idx); - } - } break; - case hashString("flip", 4): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto flipCode = args.asNumber(3); + cv::bitwise_and(*src1, *src2, *dst, *mask); + } else { + cv::bitwise_and(*src1, *src2, *dst); + } + } break; + case hashString("bitwise_not", 11): { + auto src1 = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + + if(args.isObject(3)) { + auto mask = args.asMatPtr(3); - cv::flip(*src, *dst, flipCode); - } break; - case hashString("gemm", 4): { - auto src1 = args.asMatPtr(1); - auto src2 = args.asMatPtr(2); - auto alpha = args.asNumber(3); - auto src3 = args.asMatPtr(4); - auto beta = args.asNumber(5); - auto dst = args.asMatPtr(6); - auto flags = args.asNumber(7); - - cv::gemm(*src1, *src2, alpha, *src3, beta, *dst, flags); - } break; - case hashString("getOptimalDFTSize", 17): { - auto vecsize = args.asNumber(1); - - auto result = cv::getOptimalDFTSize(vecsize); - value.setProperty(runtime, "value", result); - } break; - case hashString("hconcat", 7): { - auto srcs = args.asMatVectorPtr(1); - auto dst = args.asMatPtr(2); + cv::bitwise_not(*src1, *dst, *mask); + } else { + cv::bitwise_not(*src1, *dst); + } + } break; + case hashString("bitwise_or", 10): { + auto src1 = args.asMatPtr(1); + auto src2 = args.asMatPtr(2); + auto dst = args.asMatPtr(3); + + if(args.isObject(4)) { + auto mask = args.asMatPtr(4); - cv::hconcat(*srcs, *dst); - } break; - case hashString("idft", 4): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto flags = args.asNumber(3); - auto nonzeroRows = args.asNumber(4); + cv::bitwise_or(*src1, *src2, *dst, *mask); + } else { + cv::bitwise_or(*src1, *src2, *dst); + } + } break; + case hashString("bitwise_xor", 11): { + auto src1 = args.asMatPtr(1); + auto src2 = args.asMatPtr(2); + auto dst = args.asMatPtr(3); + + if(args.isObject(4)) { + auto mask = args.asMatPtr(4); - cv::idft(*src, *dst, flags, nonzeroRows); - } break; - case hashString("inRange", 7): { - auto src = args.asMatPtr(1); - auto lowerBound = args.asScalarPtr(2); - auto upperBound = args.asScalarPtr(3); - auto dst = args.asMatPtr(4); - - cv::inRange(*src, *lowerBound, *upperBound, *dst); - } break; - case hashString("insertChannel", 13): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto coi = args.asNumber(3); - - cv::insertChannel(*src, *dst, coi); - } break; - case hashString("invert", 6): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto flags = args.asNumber(3); - - cv::invert(*src, *dst, flags); - } break; - case hashString("log", 3): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - - cv::log(*src, *dst); - } break; - case hashString("LUT", 3): { - auto src = args.asMatPtr(1); - auto lut = args.asMatPtr(2); - auto dst = args.asMatPtr(3); - - cv::LUT(*src, *lut, *dst); - } break; - case hashString("magnitude", 9): { - auto magnitude = args.asMatPtr(3); - - if(args.isMat(1)) { - auto x = args.asMatPtr(1); - auto y = args.asMatPtr(2); - cv::magnitude(*x, *y, *magnitude); - } else { - auto x = args.asMatVectorPtr(1); - auto y = args.asMatVectorPtr(2); - cv::magnitude(*x, *y, *magnitude); - } - } break; - case hashString("Mahalanobis", 11): { - auto icovar = args.asMatPtr(3); - - if(args.isMat(1)) { - auto x = args.asMatPtr(1); - auto y = args.asMatPtr(2); - cv::Mahalanobis(*x, *y, *icovar); - } else { - auto x = args.asMatVectorPtr(1); - auto y = args.asMatVectorPtr(2); - cv::Mahalanobis(*x, *y, *icovar); - } - } break; - case hashString("max", 3): { - auto src1 = args.asMatPtr(1); - auto src2 = args.asMatPtr(2); - auto dst = args.asMatPtr(3); - - cv::max(*src1, *src2, *dst); - } break; - case hashString("mean", 4): { - auto src = args.asMatPtr(1); - std::string id = ""; - - if(args.isObject(2)) { - auto mask = args.asMatPtr(2); - - auto scalar = cv::mean(*src, *mask); - std::string id = FOCV_Storage::save(scalar); - } else { - auto scalar = cv::mean(*src); - std::string id = FOCV_Storage::save(scalar); - } - - return FOCV_JsiObject::wrap(runtime, "scalar", id); - } break; - case hashString("meanStdDev", 10): { - auto src = args.asMatPtr(1); - auto mean = args.asMatPtr(2); - auto stddev = args.asMatPtr(3); - - if(args.isObject(4)) { - auto mask = args.asMatPtr(4); - - cv::meanStdDev(*src, *mean, *stddev, *mask); - } else { - cv::meanStdDev(*src, *mean, *stddev); - } - } break; - case hashString("min", 3): { - auto src1 = args.asMatPtr(1); - auto src2 = args.asMatPtr(2); - auto dst = args.asMatPtr(3); + cv::bitwise_xor(*src1, *src2, *dst, *mask); + } else { + cv::bitwise_xor(*src1, *src2, *dst); + } + } break; + case hashString("borderInterpolate", 17): { + auto p = args.asNumber(1); + auto len = args.asNumber(2); + auto borderType = args.asNumber(3); + + auto result = cv::borderInterpolate(p, len, borderType); + value.setProperty(runtime, "value", result); + } break; + case hashString("calcCovarMatrix", 15): { + auto samples = args.asMatVectorPtr(1); + auto nsamples = args.asNumber(2); + auto covar = args.asMatPtr(3); + auto mean = args.asMatPtr(4); + auto flags = args.asNumber(5); + auto dtype = args.asNumber(6); + + cv::calcCovarMatrix((*samples).data(), nsamples, *covar, *mean, flags, dtype); + } break; + case hashString("cartToPolar", 11): { + if(args.isMat(1)) { + auto x = args.asMatPtr(1); + auto y = args.asMatPtr(2); + auto magnitude = args.asMatPtr(3); + auto angle = args.asMatPtr(4); - cv::min(*src1, *src2, *dst); - } break; - case hashString("minMaxLoc", 9): { - auto src = args.asMatPtr(1); - double min = 0; - double max = 0; - - if(args.isObject(2)) { - auto mask = args.asMatPtr(2); - - cv::minMaxIdx(*src, &min, &max, NULL, NULL, *mask); - - } else { - cv::minMaxIdx(*src, &min, &max); - } - - value.setProperty(runtime, "minVal", jsi::Value(min)); - value.setProperty(runtime, "maxVal", jsi::Value(max)); - } break; - case hashString("mulSpectrums", 12): { - auto a = args.asMatPtr(1); - auto b = args.asMatPtr(2); - auto c = args.asMatPtr(3); - auto flags = args.asNumber(4); - - if(args.isBool(5)) { - auto conjB = args.asBool(5); - - cv::mulSpectrums(*a, *b, *c, flags, conjB); - } else { - cv::mulSpectrums(*a, *b, *c, flags); - } - } break; - case hashString("multiply", 8): { - auto src1 = args.asMatPtr(1); - auto src2 = args.asMatPtr(2); - auto dst = args.asMatPtr(3); - auto scale = args.asNumber(4); - - if(args.isNumber(5)) { - auto dtype = args.asNumber(5); - - cv::multiply(*src1, *src2, *dst, scale, dtype); - } else { - cv::multiply(*src1, *src2, *dst, scale); - } - } break; - case hashString("mulTransposed", 13): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto aTa = args.asBool(3); - auto delta = args.asMatPtr(4); - auto scale = args.asNumber(5); - - if(args.isNumber(6)) { - auto dtype = args.asNumber(6); - - cv::mulTransposed(*src, *dst, aTa, *delta, scale, dtype); - } else { - cv::mulTransposed(*src, *dst, aTa, *delta, scale); - } - } break; - case hashString("norm", 4): { - auto src = args.asMatPtr(1); - auto normType = args.asNumber(2); - double norm = 0; - - if(args.isObject(3)) { - auto mask = args.asMatPtr(3); - norm = cv::norm(*src, normType, *mask); - } else { - norm = cv::norm(*src, normType); - } - - value.setProperty(runtime, "norm", jsi::Value(norm)); - } break; - case hashString("normalize", 9): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto alpha = args.asNumber(3); - auto normType = args.asNumber(4); - - cv::normalize(*src, *dst, alpha, normType); - } break; - case hashString("patchNaNs", 9): { - auto alpha = args.asNumber(2); - - if(args.isMat(1)) { - auto a = args.asMatPtr(1); - cv::patchNaNs(*a, alpha); - } else { - auto a = args.asMatVectorPtr(1); - cv::patchNaNs(*a, alpha); - } - } break; - case hashString("perspectiveTransform", 20): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto m = args.asMatPtr(3); - - cv::perspectiveTransform(*src, *dst, *m); - } break; - case hashString("phase", 5): { - auto angle = args.asMatPtr(3); - auto angleInDegrees = args.asBool(4); - - if(args.isMat(1)) { - auto x = args.asMatPtr(1); - auto y = args.asMatPtr(2); - cv::phase(*x, *y, *angle, angleInDegrees); - } else { - auto x = args.asMatVectorPtr(1); - auto y = args.asMatVectorPtr(2); - cv::phase(*x, *y, *angle, angleInDegrees); - } - } break; - case hashString("pow", 3): { - auto src = args.asMatPtr(1); - auto power = args.asNumber(2); - auto dst = args.asMatPtr(3); - - cv::pow(*src, power, *dst); - } break; - case hashString("PSNR", 4): { - auto src1 = args.asMatPtr(1); - auto src2 = args.asMatPtr(2); - auto R = args.asNumber(3); + if(args.isBool(5)) { + auto angleInDegrees = args.asBool(5); + + cv::cartToPolar(*x, *y, *magnitude, *angle, angleInDegrees); + } else { + cv::cartToPolar(*x, *y, *magnitude, *angle); + } + } else { + auto x = args.asMatVectorPtr(1); + auto y = args.asMatVectorPtr(2); + auto magnitude = args.asMatVectorPtr(3); + auto angle = args.asMatVectorPtr(4); - auto result = cv::PSNR(*src1, *src2, R); - value.setProperty(runtime, "psnr", jsi::Value(result)); - } break; - case hashString("reduce", 6): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto dim = args.asNumber(3); - auto rtype = args.asNumber(4); - auto dtype = args.asNumber(5); - - cv::reduce(*src, *dst, dim, rtype, dtype); - } break; - case hashString("repeat", 6): { - auto src = args.asMatPtr(1); - auto ny = args.asNumber(2); - auto nx = args.asNumber(3); - auto dst = args.asMatPtr(4); - - cv::repeat(*src, ny, nx, *dst); - } break; - case hashString("scaleAdd", 8): { - auto src1 = args.asMatPtr(1); - auto alpha = args.asNumber(2); - auto src2 = args.asMatPtr(3); - auto dst = args.asMatPtr(4); - - cv::scaleAdd(*src1, alpha, *src2, *dst); - } break; - case hashString("solve", 5): { - auto src1 = args.asMatPtr(1); - auto src2 = args.asMatPtr(2); - auto dst = args.asMatPtr(3); - auto flags = args.asNumber(4); - - auto result = cv::solve(*src1, *src2, *dst, flags); - value.setProperty(runtime, "resolved", jsi::Value(result)); - } break; - case hashString("solveCubic", 10): { - auto coeffs = args.asMatPtr(1); - auto roots = args.asMatPtr(2); - - auto result = cv::solveCubic(*coeffs, *roots); - value.setProperty(runtime, "value", jsi::Value(result)); - } break; - case hashString("solvePoly", 9): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto maxIters = args.asNumber(3); - - auto result = cv::solvePoly(*src, *dst, maxIters); - value.setProperty(runtime, "value", jsi::Value(result)); - } break; - case hashString("sort", 4): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto flags = args.asNumber(3); - - cv::sort(*src, *dst, flags); - } break; - case hashString("sortIdx", 7): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto flags = args.asNumber(3); - - cv::sortIdx(*src, *dst, flags); - } break; - case hashString("split", 5): { - auto src = args.asMatPtr(1); - auto dst = args.asMatVectorPtr(2); - - cv::split(*src, *dst); - } break; - case hashString("sqrt", 4): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - - cv::sqrt(*src, *dst); - } break; - case hashString("subtract", 8): { - auto src1 = args.asMatPtr(1); - auto src2 = args.asMatPtr(2); - auto dst = args.asMatPtr(3); - - if(args.isNumber(5)) { - auto mask = args.asMatPtr(4); - auto dtype = args.asNumber(5); - - cv::subtract(*src1, *src2, *dst, *mask, dtype); - } else if(args.isObject(4)) { - auto mask = args.asMatPtr(4); - - cv::subtract(*src1, *src2, *dst, *mask); - } else { - cv::subtract(*src1, *src2, *dst); - } - } break; - case hashString("sum", 3): { - std::string id = ""; - - if(args.isMat(1)) { - auto src = args.asMatPtr(1); - auto scalar = cv::sum(*src); - id = FOCV_Storage::save(scalar); - } else { - auto src = args.asMatVectorPtr(1); - auto scalar = cv::sum(*src); - id = FOCV_Storage::save(scalar); - } - - return FOCV_JsiObject::wrap(runtime, "scalar", id); - } break; - case hashString("trace", 5): { - auto src = args.asMatPtr(1); + if(args.isBool(5)) { + auto angleInDegrees = args.asBool(5); + + cv::cartToPolar(*x, *y, *magnitude, *angle, angleInDegrees); + } else { + cv::cartToPolar(*x, *y, *magnitude, *angle); + } + } + } break; + case hashString("checkRange", 10): { + auto quiet = args.asBool(2); + auto pos = args.asPointPtr(3); + auto minVal = args.asNumber(2); + auto maxVal = args.asNumber(2); + + if(args.isMat(1)) { + auto a = args.asMatPtr(1); + cv::checkRange(*a, quiet, &(*pos), minVal, maxVal); + } else { + auto a = args.asMatVectorPtr(1); + cv::checkRange(*a, quiet, &(*pos), minVal, maxVal); + } + } break; + case hashString("compare", 7): { + auto src1 = args.asMatPtr(1); + auto src2 = args.asMatPtr(2); + auto dst = args.asMatPtr(3); + auto cmpop = args.asNumber(4); + + cv::compare(*src1, *src2, *dst, cmpop); + } break; + case hashString("completeSymm", 12): { + auto lowerToUpper = args.asBool(2); + + if(args.isMat(1)) { + auto m = args.asMatPtr(1); + cv::completeSymm(*m, lowerToUpper); + } else { + auto m = args.asMatVectorPtr(1); + cv::completeSymm(*m, lowerToUpper); + } + } break; + case hashString("convertFp16", 11): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + + cv::convertFp16(*src, *dst); + } break; + case hashString("convertScaleAbs", 15): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + + if(args.isNumber(4)) { + auto alpha = args.asNumber(3); + auto beta = args.asNumber(4); - auto scalar = cv::trace(*src); - std::string id = FOCV_Storage::save(scalar); + cv::convertScaleAbs(*src, *dst, alpha, beta); + } else if(args.isNumber(3)) { + auto alpha = args.asNumber(3); - return FOCV_JsiObject::wrap(runtime, "scalar", id); - } break; - case hashString("transform", 9): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto m = args.asMatPtr(3); + cv::convertScaleAbs(*src, *dst, alpha); + } else { + cv::convertScaleAbs(*src, *dst); + } + } break; + case hashString("copyMakeBorder", 14): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto top = args.asNumber(3); + auto bottom = args.asNumber(4); + auto left = args.asNumber(5); + auto right = args.asNumber(6); + auto borderType = args.asNumber(7); + auto value = args.asScalarPtr(8); + + cv::copyMakeBorder(*src, *dst, top, bottom, left, right, borderType, *value); + } break; + case hashString("copyTo", 6): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto mask = args.asMatPtr(3); + + cv::copyTo(*src, *dst, *mask); + } break; + case hashString("countNonZero", 12): { + if(args.isMat(1)) { + auto src = args.asMatPtr(1); + auto result = cv::countNonZero(*src); + value.setProperty(runtime, "value", result); + } else { + auto src = args.asMatVectorPtr(1); + auto result = cv::countNonZero(*src); + value.setProperty(runtime, "value", result); + } + } break; + case hashString("dct", 3): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto flags = args.asNumber(3); + + cv::dct(*src, *dst, flags); + } break; + case hashString("determinant", 11): { + auto src = args.asMatPtr(1); + + auto result = cv::determinant(*src); + value.setProperty(runtime, "value", result); + } break; + case hashString("dft", 3): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto flags = args.asNumber(3); + auto nonzeroRows = args.asNumber(4); + + cv::dft(*src, *dst, flags, nonzeroRows); + } break; + case hashString("divide", 6): { + auto src1 = args.asMatPtr(1); + auto src2 = args.asMatPtr(2); + auto dst = args.asMatPtr(3); + auto scale = args.asNumber(4); + + if(args.isNumber(5)) { + auto dtype = args.asNumber(5); - cv::transform(*src, *dst, *m); - } break; - case hashString("transpose", 9): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); + cv::divide(*src1, *src2, *dst, scale, dtype); + } else { + cv::divide(*src1, *src2, *dst, scale); + } + } break; + case hashString("eigen", 5): { + auto src = args.asMatPtr(1); + auto eigenvalues = args.asMatPtr(2); + auto eigenvectors = args.asMatPtr(3); + + cv::eigen(*src, *eigenvalues, *eigenvectors); + } break; + case hashString("eigenNonSymmetric", 17): { + auto src = args.asMatPtr(1); + auto eigenvalues = args.asMatPtr(2); + auto eigenvectors = args.asMatPtr(3); + + cv::eigenNonSymmetric(*src, *eigenvalues, *eigenvectors); + } break; + case hashString("exp", 3): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + + cv::exp(*src, *dst); + } break; + case hashString("extractChannel", 14): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto coi = args.asNumber(3); + + cv::extractChannel(*src, *dst, coi); + } break; + case hashString("findNonZero", 11): { + auto src = args.asMatPtr(1); + + if(args.isMat(2)) { + auto idx = args.asMatPtr(2); + cv::findNonZero(*src, *idx); + } else { + auto idx = args.asPointVectorPtr(2); + cv::findNonZero(*src, *idx); + } + } break; + case hashString("flip", 4): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto flipCode = args.asNumber(3); + + cv::flip(*src, *dst, flipCode); + } break; + case hashString("gemm", 4): { + auto src1 = args.asMatPtr(1); + auto src2 = args.asMatPtr(2); + auto alpha = args.asNumber(3); + auto src3 = args.asMatPtr(4); + auto beta = args.asNumber(5); + auto dst = args.asMatPtr(6); + auto flags = args.asNumber(7); + + cv::gemm(*src1, *src2, alpha, *src3, beta, *dst, flags); + } break; + case hashString("getOptimalDFTSize", 17): { + auto vecsize = args.asNumber(1); + + auto result = cv::getOptimalDFTSize(vecsize); + value.setProperty(runtime, "value", result); + } break; + case hashString("hconcat", 7): { + auto srcs = args.asMatVectorPtr(1); + auto dst = args.asMatPtr(2); + + cv::hconcat(*srcs, *dst); + } break; + case hashString("idft", 4): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto flags = args.asNumber(3); + auto nonzeroRows = args.asNumber(4); + + cv::idft(*src, *dst, flags, nonzeroRows); + } break; + case hashString("inRange", 7): { + auto src = args.asMatPtr(1); + auto lowerBound = args.asScalarPtr(2); + auto upperBound = args.asScalarPtr(3); + auto dst = args.asMatPtr(4); + + cv::inRange(*src, *lowerBound, *upperBound, *dst); + } break; + case hashString("insertChannel", 13): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto coi = args.asNumber(3); + + cv::insertChannel(*src, *dst, coi); + } break; + case hashString("invert", 6): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto flags = args.asNumber(3); + + cv::invert(*src, *dst, flags); + } break; + case hashString("log", 3): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + + cv::log(*src, *dst); + } break; + case hashString("LUT", 3): { + auto src = args.asMatPtr(1); + auto lut = args.asMatPtr(2); + auto dst = args.asMatPtr(3); + + cv::LUT(*src, *lut, *dst); + } break; + case hashString("magnitude", 9): { + auto magnitude = args.asMatPtr(3); + + if(args.isMat(1)) { + auto x = args.asMatPtr(1); + auto y = args.asMatPtr(2); + cv::magnitude(*x, *y, *magnitude); + } else { + auto x = args.asMatVectorPtr(1); + auto y = args.asMatVectorPtr(2); + cv::magnitude(*x, *y, *magnitude); + } + } break; + case hashString("Mahalanobis", 11): { + auto icovar = args.asMatPtr(3); + + if(args.isMat(1)) { + auto x = args.asMatPtr(1); + auto y = args.asMatPtr(2); + cv::Mahalanobis(*x, *y, *icovar); + } else { + auto x = args.asMatVectorPtr(1); + auto y = args.asMatVectorPtr(2); + cv::Mahalanobis(*x, *y, *icovar); + } + } break; + case hashString("max", 3): { + auto src1 = args.asMatPtr(1); + auto src2 = args.asMatPtr(2); + auto dst = args.asMatPtr(3); + + cv::max(*src1, *src2, *dst); + } break; + case hashString("mean", 4): { + auto src = args.asMatPtr(1); + std::string id = ""; + + if(args.isObject(2)) { + auto mask = args.asMatPtr(2); - cv::transpose(*src, *dst); - } break; - case hashString("vconcat", 7): { - auto src = args.asMatVectorPtr(1); - auto dst = args.asMatPtr(2); + auto scalar = cv::mean(*src, *mask); + std::string id = FOCV_Storage::save(scalar); + } else { + auto scalar = cv::mean(*src); + std::string id = FOCV_Storage::save(scalar); + } + + return FOCV_JsiObject::wrap(runtime, "scalar", id); + } break; + case hashString("meanStdDev", 10): { + auto src = args.asMatPtr(1); + auto mean = args.asMatPtr(2); + auto stddev = args.asMatPtr(3); + + if(args.isObject(4)) { + auto mask = args.asMatPtr(4); - cv::vconcat(*src, *dst); - } break; - case hashString("cvtColor", 8): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto code = args.asNumber(3); - - if(args.isNumber(4)) { - auto dsnCn = args.asNumber(4); - - cv::cvtColor(*src, *dst, code, dsnCn); - } else { - cv::cvtColor(*src, *dst, code); - } - } break; - case hashString("cvtColorTwoPlane", 16): { - auto src1 = args.asMatPtr(1); - auto src2 = args.asMatPtr(2); - auto dst = args.asMatPtr(3); - auto code = args.asNumber(4); - - cv::cvtColorTwoPlane(*src1, *src2, *dst, code); - } break; - case hashString("demosaicing", 11): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto code = args.asNumber(3); - - if(args.isNumber(4)) { - auto dsnCn = args.asNumber(4); - - cv::demosaicing(*src, *dst, code, dsnCn); - } else { - cv::demosaicing(*src, *dst, code); - } - } break; - case hashString("applyColorMap", 13): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto colormap = args.asNumber(3); - - cv::applyColorMap(*src, *dst, colormap); - } break; - case hashString("arrowedLine", 11): { - auto img = args.asMatPtr(1); - auto point1 = args.asPointPtr(2); - auto point2 = args.asPointPtr(3); - auto color = args.asScalarPtr(4); - auto thickness = args.asNumber(5); - auto line_type = args.asNumber(6); - - cv::arrowedLine(*img, *point1, *point2, *color, thickness, line_type); - } break; - case hashString("circle", 6): { - auto img = args.asMatPtr(1); - auto center = args.asPointPtr(2); - auto radius = args.asNumber(3); - auto color = args.asScalarPtr(4); - auto thickness = args.asNumber(5); - auto line_type = args.asNumber(6); - - cv::circle(*img, *center, radius, *color, thickness, line_type); - } break; - case hashString("clipLine", 8): { - auto size = args.asSizePtr(1); - auto point1 = args.asPointPtr(2); - auto point2 = args.asPointPtr(3); - - auto result = cv::clipLine(*size, *point1, *point2); - value.setProperty(runtime, "value", jsi::Value(result)); - } break; - case hashString("drawContours", 12): { - auto img = args.asMatPtr(1); - auto contours = args.asMatVectorPtr(2); - auto contourIdx = args.asNumber(3); - auto color = args.asScalarPtr(4); - auto thickness = args.asNumber(5); - auto line_type = args.asNumber(6); - - cv::drawContours(*img, *contours, contourIdx, *color, thickness, line_type); - } break; - case hashString("drawMarker", 10): { - auto img = args.asMatPtr(1); - auto position = args.asPointPtr(2); - auto color = args.asScalarPtr(3); - auto markerType = args.asNumber(4); - auto markerSize = args.asNumber(5); - auto thickness = args.asNumber(6); - auto line_type = args.asNumber(7); - - cv::drawMarker(*img, *position, *color, markerType, markerSize, thickness, line_type); - } break; - case hashString("ellipse", 7): { - auto img = args.asMatPtr(1); - auto center = args.asPointPtr(2); - auto axes = args.asSizePtr(3); - auto angle = args.asNumber(4); - auto startAngle = args.asNumber(5); - auto endAngle = args.asNumber(6); - auto color = args.asScalarPtr(7); - auto thickness = args.asNumber(8); - auto line_type = args.asNumber(9); - - cv::ellipse(*img, *center, *axes, angle, startAngle, endAngle, *color, thickness, line_type); - } break; - case hashString("fillConvexPoly", 14): { - auto img = args.asMatPtr(1); - auto pts = args.asMatVectorPtr(2); - auto color = args.asScalarPtr(3); - auto line_type = args.asNumber(4); - - cv::fillConvexPoly(*img, *pts, *color, line_type); - } break; - case hashString("fillPoly", 8): { - auto img = args.asMatPtr(1); - auto pts = args.asMatVectorPtr(2); - auto color = args.asScalarPtr(3); - auto line_type = args.asNumber(4); - - cv::fillPoly(*img, *pts, *color, line_type); - } break; - case hashString("line", 4): { - auto img = args.asMatPtr(1); - auto point1 = args.asPointPtr(2); - auto point2 = args.asPointPtr(3); - auto color = args.asScalarPtr(4); - auto thickness = args.asNumber(5); - auto line_type = args.asNumber(6); - - cv::line(*img, *point1, *point2, *color, thickness, line_type); - } break; - case hashString("polylines", 9): { - auto img = args.asMatPtr(1); - auto pts = args.asMatVectorPtr(2); - auto isClosed = args.asBool(3); - auto color = args.asScalarPtr(4); - auto thickness = args.asNumber(5); - auto line_type = args.asNumber(6); - - cv::polylines(*img, *pts, isClosed, *color, thickness, line_type); - } break; - case hashString("rectangle", 9): { - auto img = args.asMatPtr(1); - auto point1 = args.asPointPtr(2); - auto point2 = args.asPointPtr(3); - auto color = args.asScalarPtr(4); - auto thickness = args.asNumber(5); - auto line_type = args.asNumber(6); - - cv::rectangle(*img, *point1, *point2, *color, thickness, line_type); - } break; - case hashString("Canny", 5): { - auto image = args.asMatPtr(1); - auto edges = args.asMatPtr(2); - auto threshold1 = args.asNumber(3); - auto threshold2 = args.asNumber(4); - - cv::Canny(*image, *edges, threshold1, threshold2); - } break; - case hashString("cornerHarris", 12): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto blockSize = args.asNumber(3); - auto ksize = args.asNumber(4); - auto k = args.asNumber(5); - - cv::cornerHarris(*src, *dst, blockSize, ksize, k); - } break; - case hashString("cornerMinEigenVal", 17): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto blockSize = args.asNumber(3); - - cv::cornerMinEigenVal(*src, *dst, blockSize); - } break; - case hashString("goodFeaturesToTrack", 19): { - auto image = args.asMatPtr(1); - auto corners = args.asMatPtr(2); - auto maxCorners = args.asNumber(3); - auto qualityLevel = args.asNumber(4); - auto minDistance = args.asNumber(5); - - cv::goodFeaturesToTrack(*image, *corners, maxCorners, qualityLevel, minDistance); - } break; - case hashString("HoughCircles", 12): { - auto image = args.asMatPtr(1); - auto circles = args.asMatPtr(2); - auto method = args.asNumber(3); - auto dp = args.asNumber(4); - auto minDist = args.asNumber(5); - - if(args.isNumber(7)) { - auto param1 = args.asNumber(6); - auto param2 = args.asNumber(7); - - cv::HoughCircles(*image, *circles, method, dp, minDist, param1, param2); - } else if(args.isNumber(6)) { - auto param1 = args.asNumber(6); - - cv::HoughCircles(*image, *circles, method, dp, minDist, param1); - } else { - cv::HoughCircles(*image, *circles, method, dp, minDist); - } - } break; - case hashString("HoughLines", 10): { - auto image = args.asMatPtr(1); - auto lines = args.asMatPtr(2); - auto rho = args.asNumber(3); - auto theta = args.asNumber(4); - auto threshold = args.asNumber(5); + cv::meanStdDev(*src, *mean, *stddev, *mask); + } else { + cv::meanStdDev(*src, *mean, *stddev); + } + } break; + case hashString("min", 3): { + auto src1 = args.asMatPtr(1); + auto src2 = args.asMatPtr(2); + auto dst = args.asMatPtr(3); + + cv::min(*src1, *src2, *dst); + } break; + case hashString("minMaxLoc", 9): { + auto src = args.asMatPtr(1); + double min = 0; + double max = 0; + + if(args.isObject(2)) { + auto mask = args.asMatPtr(2); - cv::HoughLines(*image, *lines, rho, theta, threshold); - } break; - case hashString("HoughLinesP", 11): { - auto image = args.asMatPtr(1); - auto lines = args.asMatPtr(2); - auto rho = args.asNumber(3); - auto theta = args.asNumber(4); - auto threshold = args.asNumber(5); + cv::minMaxIdx(*src, &min, &max, NULL, NULL, *mask); - cv::HoughLinesP(*image, *lines, rho, theta, threshold); - } break; - case hashString("bilateralFilter", 15): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto d = args.asNumber(3); - auto sigmaColor = args.asNumber(4); - auto sigmaSpace = args.asNumber(5); - auto borderType = args.asNumber(6); + } else { + cv::minMaxIdx(*src, &min, &max); + } + + value.setProperty(runtime, "minVal", jsi::Value(min)); + value.setProperty(runtime, "maxVal", jsi::Value(max)); + } break; + case hashString("mulSpectrums", 12): { + auto a = args.asMatPtr(1); + auto b = args.asMatPtr(2); + auto c = args.asMatPtr(3); + auto flags = args.asNumber(4); + + if(args.isBool(5)) { + auto conjB = args.asBool(5); - cv::bilateralFilter(*src, *dst, d, sigmaColor, sigmaSpace, borderType); - } break; - case hashString("blur", 4): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto ksize = args.asSizePtr(3); - auto anchor = args.asPointPtr(4); - auto borderType = args.asNumber(5); + cv::mulSpectrums(*a, *b, *c, flags, conjB); + } else { + cv::mulSpectrums(*a, *b, *c, flags); + } + } break; + case hashString("multiply", 8): { + auto src1 = args.asMatPtr(1); + auto src2 = args.asMatPtr(2); + auto dst = args.asMatPtr(3); + auto scale = args.asNumber(4); + + if(args.isNumber(5)) { + auto dtype = args.asNumber(5); - cv::blur(*src, *dst, *ksize, *anchor, borderType); - } break; - case hashString("boxFilter", 9): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto ddepth = args.asNumber(3); - auto ksize = args.asSizePtr(4); - auto anchor = args.asPointPtr(5); - auto normalize = args.asBool(6); - auto borderType = args.asNumber(7); + cv::multiply(*src1, *src2, *dst, scale, dtype); + } else { + cv::multiply(*src1, *src2, *dst, scale); + } + } break; + case hashString("mulTransposed", 13): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto aTa = args.asBool(3); + auto delta = args.asMatPtr(4); + auto scale = args.asNumber(5); + + if(args.isNumber(6)) { + auto dtype = args.asNumber(6); - cv::boxFilter(*src, *dst, ddepth, *ksize, *anchor, normalize, borderType); - } break; - case hashString("buildPyramid", 12): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto maxlevel = args.asNumber(3); - auto borderType = args.asNumber(4); + cv::mulTransposed(*src, *dst, aTa, *delta, scale, dtype); + } else { + cv::mulTransposed(*src, *dst, aTa, *delta, scale); + } + } break; + case hashString("norm", 4): { + auto src = args.asMatPtr(1); + auto normType = args.asNumber(2); + double norm = 0; + + if(args.isObject(3)) { + auto mask = args.asMatPtr(3); + norm = cv::norm(*src, normType, *mask); + } else { + norm = cv::norm(*src, normType); + } + + value.setProperty(runtime, "norm", jsi::Value(norm)); + } break; + case hashString("normalize", 9): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto alpha = args.asNumber(3); + auto normType = args.asNumber(4); + + cv::normalize(*src, *dst, alpha, normType); + } break; + case hashString("patchNaNs", 9): { + auto alpha = args.asNumber(2); + + if(args.isMat(1)) { + auto a = args.asMatPtr(1); + cv::patchNaNs(*a, alpha); + } else { + auto a = args.asMatVectorPtr(1); + cv::patchNaNs(*a, alpha); + } + } break; + case hashString("perspectiveTransform", 20): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto m = args.asMatPtr(3); + + cv::perspectiveTransform(*src, *dst, *m); + } break; + case hashString("phase", 5): { + auto angle = args.asMatPtr(3); + auto angleInDegrees = args.asBool(4); + + if(args.isMat(1)) { + auto x = args.asMatPtr(1); + auto y = args.asMatPtr(2); + cv::phase(*x, *y, *angle, angleInDegrees); + } else { + auto x = args.asMatVectorPtr(1); + auto y = args.asMatVectorPtr(2); + cv::phase(*x, *y, *angle, angleInDegrees); + } + } break; + case hashString("pow", 3): { + auto src = args.asMatPtr(1); + auto power = args.asNumber(2); + auto dst = args.asMatPtr(3); + + cv::pow(*src, power, *dst); + } break; + case hashString("PSNR", 4): { + auto src1 = args.asMatPtr(1); + auto src2 = args.asMatPtr(2); + auto R = args.asNumber(3); + + auto result = cv::PSNR(*src1, *src2, R); + value.setProperty(runtime, "psnr", jsi::Value(result)); + } break; + case hashString("reduce", 6): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto dim = args.asNumber(3); + auto rtype = args.asNumber(4); + auto dtype = args.asNumber(5); + + cv::reduce(*src, *dst, dim, rtype, dtype); + } break; + case hashString("repeat", 6): { + auto src = args.asMatPtr(1); + auto ny = args.asNumber(2); + auto nx = args.asNumber(3); + auto dst = args.asMatPtr(4); + + cv::repeat(*src, ny, nx, *dst); + } break; + case hashString("scaleAdd", 8): { + auto src1 = args.asMatPtr(1); + auto alpha = args.asNumber(2); + auto src2 = args.asMatPtr(3); + auto dst = args.asMatPtr(4); + + cv::scaleAdd(*src1, alpha, *src2, *dst); + } break; + case hashString("solve", 5): { + auto src1 = args.asMatPtr(1); + auto src2 = args.asMatPtr(2); + auto dst = args.asMatPtr(3); + auto flags = args.asNumber(4); + + auto result = cv::solve(*src1, *src2, *dst, flags); + value.setProperty(runtime, "resolved", jsi::Value(result)); + } break; + case hashString("solveCubic", 10): { + auto coeffs = args.asMatPtr(1); + auto roots = args.asMatPtr(2); + + auto result = cv::solveCubic(*coeffs, *roots); + value.setProperty(runtime, "value", jsi::Value(result)); + } break; + case hashString("solvePoly", 9): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto maxIters = args.asNumber(3); + + auto result = cv::solvePoly(*src, *dst, maxIters); + value.setProperty(runtime, "value", jsi::Value(result)); + } break; + case hashString("sort", 4): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto flags = args.asNumber(3); + + cv::sort(*src, *dst, flags); + } break; + case hashString("sortIdx", 7): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto flags = args.asNumber(3); + + cv::sortIdx(*src, *dst, flags); + } break; + case hashString("split", 5): { + auto src = args.asMatPtr(1); + auto dst = args.asMatVectorPtr(2); + + cv::split(*src, *dst); + } break; + case hashString("sqrt", 4): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + + cv::sqrt(*src, *dst); + } break; + case hashString("subtract", 8): { + auto src1 = args.asMatPtr(1); + auto src2 = args.asMatPtr(2); + auto dst = args.asMatPtr(3); + + if(args.isNumber(5)) { + auto mask = args.asMatPtr(4); + auto dtype = args.asNumber(5); - cv::buildPyramid(*src, *dst, maxlevel, borderType); - } break; - case hashString("dilate", 6): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto kernel = args.asMatPtr(3); - auto anchor = args.asPointPtr(4); - auto iterations = args.asNumber(5); - auto borderType = args.asNumber(6); - auto borderValue = args.asScalarPtr(7); - - cv::dilate(*src, *dst, *kernel, *anchor, iterations, borderType, *borderValue); - } break; - case hashString("erode", 5): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto kernel = args.asMatPtr(3); - auto anchor = args.asPointPtr(4); - auto iterations = args.asNumber(5); - auto borderType = args.asNumber(6); - auto borderValue = args.asScalarPtr(7); - - cv::erode(*src, *dst, *kernel, *anchor, iterations, borderType, *borderValue); - } break; - case hashString("filter2D", 8): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto ddepth = args.asNumber(3); - auto kernel = args.asMatPtr(4); - auto anchor = args.asPointPtr(5); - auto delat = args.asNumber(6); - auto borderType = args.asNumber(7); - - cv::filter2D(*src, *dst, ddepth, *kernel, *anchor, delat, borderType); - } break; - case hashString("GaussianBlur", 12): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto ksize = args.asSizePtr(3); - auto sigmaX = args.asNumber(4); - auto sigmaY = args.asNumber(5); - auto borderType = args.asNumber(6); - - cv::GaussianBlur(*src, *dst, *ksize, sigmaX, sigmaY, borderType); - } break; - case hashString("getGaborKernel", 14): { - auto ksize = args.asSizePtr(1); - auto sigma = args.asNumber(2); - auto theta = args.asNumber(3); - auto lambd = args.asNumber(4); - auto gamma = args.asNumber(5); - auto psi = args.asNumber(6); - auto ktype = args.asNumber(7); - - cv::Mat result = cv::getGaborKernel(*ksize, sigma, theta, lambd, gamma, psi, ktype); - std::string id = FOCV_Storage::save(result); + cv::subtract(*src1, *src2, *dst, *mask, dtype); + } else if(args.isObject(4)) { + auto mask = args.asMatPtr(4); - return FOCV_JsiObject::wrap(runtime, "mat", id); - } break; - case hashString("getGaussianKernel", 17): { - auto ksize = args.asNumber(1); - auto sigma = args.asNumber(2); - auto ktype = args.asNumber(3); - - cv::Mat result = cv::getGaussianKernel(ksize, sigma, ktype); - std::string id = FOCV_Storage::save(result); + cv::subtract(*src1, *src2, *dst, *mask); + } else { + cv::subtract(*src1, *src2, *dst); + } + } break; + case hashString("sum", 3): { + std::string id = ""; + + if(args.isMat(1)) { + auto src = args.asMatPtr(1); + auto scalar = cv::sum(*src); + id = FOCV_Storage::save(scalar); + } else { + auto src = args.asMatVectorPtr(1); + auto scalar = cv::sum(*src); + id = FOCV_Storage::save(scalar); + } + + return FOCV_JsiObject::wrap(runtime, "scalar", id); + } break; + case hashString("trace", 5): { + auto src = args.asMatPtr(1); + + auto scalar = cv::trace(*src); + std::string id = FOCV_Storage::save(scalar); + + return FOCV_JsiObject::wrap(runtime, "scalar", id); + } break; + case hashString("transform", 9): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto m = args.asMatPtr(3); + + cv::transform(*src, *dst, *m); + } break; + case hashString("transpose", 9): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + + cv::transpose(*src, *dst); + } break; + case hashString("vconcat", 7): { + auto src = args.asMatVectorPtr(1); + auto dst = args.asMatPtr(2); + + cv::vconcat(*src, *dst); + } break; + case hashString("cvtColor", 8): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto code = args.asNumber(3); + + if(args.isNumber(4)) { + auto dsnCn = args.asNumber(4); - return FOCV_JsiObject::wrap(runtime, "mat", id); - } break; - case hashString("Laplacian", 9): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto ddepth = args.asNumber(3); - auto ksize = args.asNumber(4); - auto scale = args.asNumber(5); - auto delta = args.asNumber(6); - auto borderType = args.asNumber(7); - - cv::Laplacian(*src, *dst, ddepth, ksize, scale, delta, borderType); - } break; - case hashString("medianBlur", 10): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto ksize = args.asNumber(3); + cv::cvtColor(*src, *dst, code, dsnCn); + } else { + cv::cvtColor(*src, *dst, code); + } + } break; + case hashString("cvtColorTwoPlane", 16): { + auto src1 = args.asMatPtr(1); + auto src2 = args.asMatPtr(2); + auto dst = args.asMatPtr(3); + auto code = args.asNumber(4); + + cv::cvtColorTwoPlane(*src1, *src2, *dst, code); + } break; + case hashString("demosaicing", 11): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto code = args.asNumber(3); + + if(args.isNumber(4)) { + auto dsnCn = args.asNumber(4); - cv::medianBlur(*src, *dst, ksize); - } break; - case hashString("morphologyEx", 12): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto op = args.asNumber(3); - auto kernel = args.asMatPtr(4); - auto anchor = args.asPointPtr(5); - auto iterations = args.asNumber(6); - auto borderType = args.asNumber(7); - auto borderValue = args.asScalarPtr(8); + cv::demosaicing(*src, *dst, code, dsnCn); + } else { + cv::demosaicing(*src, *dst, code); + } + } break; + case hashString("applyColorMap", 13): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto colormap = args.asNumber(3); + + cv::applyColorMap(*src, *dst, colormap); + } break; + case hashString("arrowedLine", 11): { + auto img = args.asMatPtr(1); + auto point1 = args.asPointPtr(2); + auto point2 = args.asPointPtr(3); + auto color = args.asScalarPtr(4); + auto thickness = args.asNumber(5); + auto line_type = args.asNumber(6); + + cv::arrowedLine(*img, *point1, *point2, *color, thickness, line_type); + } break; + case hashString("circle", 6): { + auto img = args.asMatPtr(1); + auto center = args.asPointPtr(2); + auto radius = args.asNumber(3); + auto color = args.asScalarPtr(4); + auto thickness = args.asNumber(5); + auto line_type = args.asNumber(6); + + cv::circle(*img, *center, radius, *color, thickness, line_type); + } break; + case hashString("clipLine", 8): { + auto size = args.asSizePtr(1); + auto point1 = args.asPointPtr(2); + auto point2 = args.asPointPtr(3); + + auto result = cv::clipLine(*size, *point1, *point2); + value.setProperty(runtime, "value", jsi::Value(result)); + } break; + case hashString("drawContours", 12): { + auto img = args.asMatPtr(1); + auto contours = args.asMatVectorPtr(2); + auto contourIdx = args.asNumber(3); + auto color = args.asScalarPtr(4); + auto thickness = args.asNumber(5); + auto line_type = args.asNumber(6); + + cv::drawContours(*img, *contours, contourIdx, *color, thickness, line_type); + } break; + case hashString("drawMarker", 10): { + auto img = args.asMatPtr(1); + auto position = args.asPointPtr(2); + auto color = args.asScalarPtr(3); + auto markerType = args.asNumber(4); + auto markerSize = args.asNumber(5); + auto thickness = args.asNumber(6); + auto line_type = args.asNumber(7); + + cv::drawMarker(*img, *position, *color, markerType, markerSize, thickness, line_type); + } break; + case hashString("ellipse", 7): { + auto img = args.asMatPtr(1); + auto center = args.asPointPtr(2); + auto axes = args.asSizePtr(3); + auto angle = args.asNumber(4); + auto startAngle = args.asNumber(5); + auto endAngle = args.asNumber(6); + auto color = args.asScalarPtr(7); + auto thickness = args.asNumber(8); + auto line_type = args.asNumber(9); + + cv::ellipse(*img, *center, *axes, angle, startAngle, endAngle, *color, thickness, line_type); + } break; + case hashString("fillConvexPoly", 14): { + auto img = args.asMatPtr(1); + auto pts = args.asMatVectorPtr(2); + auto color = args.asScalarPtr(3); + auto line_type = args.asNumber(4); + + cv::fillConvexPoly(*img, *pts, *color, line_type); + } break; + case hashString("fillPoly", 8): { + auto img = args.asMatPtr(1); + auto pts = args.asMatVectorPtr(2); + auto color = args.asScalarPtr(3); + auto line_type = args.asNumber(4); + + cv::fillPoly(*img, *pts, *color, line_type); + } break; + case hashString("line", 4): { + auto img = args.asMatPtr(1); + auto point1 = args.asPointPtr(2); + auto point2 = args.asPointPtr(3); + auto color = args.asScalarPtr(4); + auto thickness = args.asNumber(5); + auto line_type = args.asNumber(6); + + cv::line(*img, *point1, *point2, *color, thickness, line_type); + } break; + case hashString("polylines", 9): { + auto img = args.asMatPtr(1); + auto pts = args.asMatVectorPtr(2); + auto isClosed = args.asBool(3); + auto color = args.asScalarPtr(4); + auto thickness = args.asNumber(5); + auto line_type = args.asNumber(6); + + cv::polylines(*img, *pts, isClosed, *color, thickness, line_type); + } break; + case hashString("rectangle", 9): { + auto img = args.asMatPtr(1); + auto point1 = args.asPointPtr(2); + auto point2 = args.asPointPtr(3); + auto color = args.asScalarPtr(4); + auto thickness = args.asNumber(5); + auto line_type = args.asNumber(6); + + cv::rectangle(*img, *point1, *point2, *color, thickness, line_type); + } break; + case hashString("Canny", 5): { + auto image = args.asMatPtr(1); + auto edges = args.asMatPtr(2); + auto threshold1 = args.asNumber(3); + auto threshold2 = args.asNumber(4); + + cv::Canny(*image, *edges, threshold1, threshold2); + } break; + case hashString("cornerHarris", 12): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto blockSize = args.asNumber(3); + auto ksize = args.asNumber(4); + auto k = args.asNumber(5); + + cv::cornerHarris(*src, *dst, blockSize, ksize, k); + } break; + case hashString("cornerMinEigenVal", 17): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto blockSize = args.asNumber(3); + + cv::cornerMinEigenVal(*src, *dst, blockSize); + } break; + case hashString("goodFeaturesToTrack", 19): { + auto image = args.asMatPtr(1); + auto corners = args.asMatPtr(2); + auto maxCorners = args.asNumber(3); + auto qualityLevel = args.asNumber(4); + auto minDistance = args.asNumber(5); + + cv::goodFeaturesToTrack(*image, *corners, maxCorners, qualityLevel, minDistance); + } break; + case hashString("HoughCircles", 12): { + auto image = args.asMatPtr(1); + auto circles = args.asMatPtr(2); + auto method = args.asNumber(3); + auto dp = args.asNumber(4); + auto minDist = args.asNumber(5); + + if(args.isNumber(7)) { + auto param1 = args.asNumber(6); + auto param2 = args.asNumber(7); - cv::morphologyEx(*src, *dst, op, *kernel, *anchor, iterations, borderType, *borderValue); - } break; - case hashString("adaptiveThreshold", 17): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto maxValue = args.asNumber(3); - auto adaptiveMethod = args.asNumber(4); - auto thresholdType = args.asNumber(5); - auto blockSize = args.asNumber(6); - auto C = args.asNumber(7); + cv::HoughCircles(*image, *circles, method, dp, minDist, param1, param2); + } else if(args.isNumber(6)) { + auto param1 = args.asNumber(6); - cv::adaptiveThreshold(*src, *dst, maxValue, adaptiveMethod, thresholdType, blockSize, C); - } break; - case hashString("distanceTransform", 17): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto distanceType = args.asNumber(3); - auto maskSize = args.asNumber(4); - - cv::distanceTransform(*src, *dst, distanceType, maskSize); - } break; - case hashString("integral", 8): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - - cv::integral(*src, *dst); - } break; - case hashString("threshold", 9): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto thresh = args.asNumber(3); - auto maxval = args.asNumber(4); - auto type = args.asNumber(5); - - cv::threshold(*src, *dst, thresh, maxval, type); - } break; - case hashString("matchTemplate", 13): { - auto image = args.asMatPtr(1); - auto templ = args.asMatPtr(2); - auto result = args.asMatPtr(3); - auto method = args.asNumber(4); - auto mask = args.asMatPtr(5); - - cv::matchTemplate(*image, *templ, *result, method, *mask); - } break; - case hashString("approxPolyDP", 12): { - auto approxCurve = args.asMatPtr(2); - auto epsilon = args.asNumber(3); - auto closed = args.asBool(4); - - if(args.isMat(1)) { - auto curve = args.asMatPtr(1); - cv::approxPolyDP(*curve, *approxCurve, epsilon, closed); - } else { - auto curve = args.asMatVectorPtr(1); - cv::approxPolyDP(*curve, *approxCurve, epsilon, closed); - } - } break; - case hashString("arcLength", 9): { - auto closed = args.asBool(2); - - if(args.isMat(1)) { - auto curve = args.asMatPtr(1); - auto result = cv::arcLength(*curve, closed); - value.setProperty(runtime, "value", jsi::Value(result)); - } else { - auto curve = args.asMatVectorPtr(1); - auto result = cv::arcLength(*curve, closed); - value.setProperty(runtime, "value", jsi::Value(result)); - } - } break; - case hashString("boundingRect", 12): { - cv::Rect rect; - - if(args.isMat(1)) { - rect = cv::boundingRect(*args.asMatPtr(1)); - } else if(args.isMatVector(1)) { - rect = cv::boundingRect(*args.asMatVectorPtr(1)); - } else { - rect = cv::boundingRect(*args.asPointVectorPtr(1)); - } - - std::string id = FOCV_Storage::save(rect); - - return FOCV_JsiObject::wrap(runtime, "rect", id); - } break; - case hashString("connectedComponents", 19): { - auto image = args.asMatPtr(1); - auto labels = args.asMatPtr(2); - - auto result = cv::connectedComponents(*image, *labels); - value.setProperty(runtime, "value", jsi::Value(result)); - } break; - case hashString("connectedComponentsWithStats", 28): { - auto image = args.asMatPtr(1); - auto labels = args.asMatPtr(2); - auto stats = args.asMatPtr(3); - auto centroids = args.asMatPtr(4); - - auto result = cv::connectedComponentsWithStats(*image, *labels, *stats, *centroids); - value.setProperty(runtime, "value", jsi::Value(result)); - } break; - case hashString("contourArea", 11): { - auto oriented = args.asBool(2); - - if(args.isMat(1)) { - auto src = args.asMatPtr(1); - value.setProperty(runtime, "value", contourArea(*src, oriented)); - } else { - auto src = args.asPointVectorPtr(1); - value.setProperty(runtime, "value", contourArea(*src, oriented)); - } - } break; - case hashString("convexHull", 10): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - - cv::convexHull(*src, *dst); - } break; - case hashString("convexityDefects", 16): { - auto contour = args.asMatPtr(1); - auto convexHull = args.asMatPtr(2); - auto convexityDefects = args.asMatPtr(3); - - cv::convexityDefects(*contour, *convexHull, *convexityDefects); - } break; - case hashString("findContours", 12): { - auto src = args.asMatPtr(1); - auto mode = args.asNumber(3); - auto method = args.asNumber(4); - - if(args.isMatVector(2)) { - auto dst = args.asMatVectorPtr(2); - cv::findContours(*src, *dst, mode, method); - } else { - auto dst = args.asPointVectorOfVectorsPtr(2); - cv::findContours(*src, *dst, mode, method); - } - } break; - case hashString("fitLine", 7): { - auto points = args.asMatPtr(1); - auto line = args.asMatPtr(2); - auto disType = args.asNumber(3); - auto param = args.asNumber(4); - auto reps = args.asNumber(5); - auto aeps = args.asNumber(6); - - cv::fitLine(*points, *line, disType, param, reps, aeps); - } break; - case hashString("isContourConvex", 15): { - auto contour = args.asMatPtr(1); - - value.setProperty(runtime, "value", jsi::Value(cv::isContourConvex(*contour))); - } break; - case hashString("matchShapes", 11): { - auto contour1 = args.asMatPtr(1); - auto contour2 = args.asMatPtr(2); - auto method = args.asNumber(3); - auto parameter = args.asNumber(4); - - auto result = cv::matchShapes(*contour1, *contour2, method, parameter); - value.setProperty(runtime, "value", jsi::Value(result)); - } break; - case hashString("minAreaRect", 11): { - auto src = args.asMatPtr(1); - - auto rect = cv::minAreaRect(*src); - - auto id = FOCV_Storage::save(rect); - return FOCV_JsiObject::wrap(runtime, "rotated_rect", id); - } break; - case hashString("convertTo", 9): { - auto src = args.asMatPtr(1); - auto dst = args.asMatPtr(2); - auto rtype = args.asNumber(3); - - (*src).convertTo(*dst, rtype); - } break; + cv::HoughCircles(*image, *circles, method, dp, minDist, param1); + } else { + cv::HoughCircles(*image, *circles, method, dp, minDist); + } + } break; + case hashString("HoughLines", 10): { + auto image = args.asMatPtr(1); + auto lines = args.asMatPtr(2); + auto rho = args.asNumber(3); + auto theta = args.asNumber(4); + auto threshold = args.asNumber(5); + + cv::HoughLines(*image, *lines, rho, theta, threshold); + } break; + case hashString("HoughLinesP", 11): { + auto image = args.asMatPtr(1); + auto lines = args.asMatPtr(2); + auto rho = args.asNumber(3); + auto theta = args.asNumber(4); + auto threshold = args.asNumber(5); + + cv::HoughLinesP(*image, *lines, rho, theta, threshold); + } break; + case hashString("bilateralFilter", 15): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto d = args.asNumber(3); + auto sigmaColor = args.asNumber(4); + auto sigmaSpace = args.asNumber(5); + auto borderType = args.asNumber(6); + + cv::bilateralFilter(*src, *dst, d, sigmaColor, sigmaSpace, borderType); + } break; + case hashString("blur", 4): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto ksize = args.asSizePtr(3); + auto anchor = args.asPointPtr(4); + auto borderType = args.asNumber(5); + + cv::blur(*src, *dst, *ksize, *anchor, borderType); + } break; + case hashString("boxFilter", 9): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto ddepth = args.asNumber(3); + auto ksize = args.asSizePtr(4); + auto anchor = args.asPointPtr(5); + auto normalize = args.asBool(6); + auto borderType = args.asNumber(7); + + cv::boxFilter(*src, *dst, ddepth, *ksize, *anchor, normalize, borderType); + } break; + case hashString("buildPyramid", 12): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto maxlevel = args.asNumber(3); + auto borderType = args.asNumber(4); + + cv::buildPyramid(*src, *dst, maxlevel, borderType); + } break; + case hashString("dilate", 6): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto kernel = args.asMatPtr(3); + auto anchor = args.asPointPtr(4); + auto iterations = args.asNumber(5); + auto borderType = args.asNumber(6); + auto borderValue = args.asScalarPtr(7); + + cv::dilate(*src, *dst, *kernel, *anchor, iterations, borderType, *borderValue); + } break; + case hashString("erode", 5): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto kernel = args.asMatPtr(3); + auto anchor = args.asPointPtr(4); + auto iterations = args.asNumber(5); + auto borderType = args.asNumber(6); + auto borderValue = args.asScalarPtr(7); + + cv::erode(*src, *dst, *kernel, *anchor, iterations, borderType, *borderValue); + } break; + case hashString("filter2D", 8): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto ddepth = args.asNumber(3); + auto kernel = args.asMatPtr(4); + auto anchor = args.asPointPtr(5); + auto delat = args.asNumber(6); + auto borderType = args.asNumber(7); + + cv::filter2D(*src, *dst, ddepth, *kernel, *anchor, delat, borderType); + } break; + case hashString("GaussianBlur", 12): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto ksize = args.asSizePtr(3); + auto sigmaX = args.asNumber(4); + auto sigmaY = args.asNumber(5); + auto borderType = args.asNumber(6); + + cv::GaussianBlur(*src, *dst, *ksize, sigmaX, sigmaY, borderType); + } break; + case hashString("getGaborKernel", 14): { + auto ksize = args.asSizePtr(1); + auto sigma = args.asNumber(2); + auto theta = args.asNumber(3); + auto lambd = args.asNumber(4); + auto gamma = args.asNumber(5); + auto psi = args.asNumber(6); + auto ktype = args.asNumber(7); + + cv::Mat result = cv::getGaborKernel(*ksize, sigma, theta, lambd, gamma, psi, ktype); + std::string id = FOCV_Storage::save(result); + + return FOCV_JsiObject::wrap(runtime, "mat", id); + } break; + case hashString("getGaussianKernel", 17): { + auto ksize = args.asNumber(1); + auto sigma = args.asNumber(2); + auto ktype = args.asNumber(3); + + cv::Mat result = cv::getGaussianKernel(ksize, sigma, ktype); + std::string id = FOCV_Storage::save(result); + + return FOCV_JsiObject::wrap(runtime, "mat", id); + } break; + case hashString("Laplacian", 9): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto ddepth = args.asNumber(3); + auto ksize = args.asNumber(4); + auto scale = args.asNumber(5); + auto delta = args.asNumber(6); + auto borderType = args.asNumber(7); + + cv::Laplacian(*src, *dst, ddepth, ksize, scale, delta, borderType); + } break; + case hashString("medianBlur", 10): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto ksize = args.asNumber(3); + + cv::medianBlur(*src, *dst, ksize); + } break; + case hashString("morphologyEx", 12): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto op = args.asNumber(3); + auto kernel = args.asMatPtr(4); + auto anchor = args.asPointPtr(5); + auto iterations = args.asNumber(6); + auto borderType = args.asNumber(7); + auto borderValue = args.asScalarPtr(8); + + cv::morphologyEx(*src, *dst, op, *kernel, *anchor, iterations, borderType, *borderValue); + } break; + case hashString("adaptiveThreshold", 17): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto maxValue = args.asNumber(3); + auto adaptiveMethod = args.asNumber(4); + auto thresholdType = args.asNumber(5); + auto blockSize = args.asNumber(6); + auto C = args.asNumber(7); + + cv::adaptiveThreshold(*src, *dst, maxValue, adaptiveMethod, thresholdType, blockSize, C); + } break; + case hashString("distanceTransform", 17): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto distanceType = args.asNumber(3); + auto maskSize = args.asNumber(4); + + cv::distanceTransform(*src, *dst, distanceType, maskSize); + } break; + case hashString("integral", 8): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + + cv::integral(*src, *dst); + } break; + case hashString("threshold", 9): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto thresh = args.asNumber(3); + auto maxval = args.asNumber(4); + auto type = args.asNumber(5); + + cv::threshold(*src, *dst, thresh, maxval, type); + } break; + case hashString("matchTemplate", 13): { + auto image = args.asMatPtr(1); + auto templ = args.asMatPtr(2); + auto result = args.asMatPtr(3); + auto method = args.asNumber(4); + auto mask = args.asMatPtr(5); + + cv::matchTemplate(*image, *templ, *result, method, *mask); + } break; + case hashString("approxPolyDP", 12): { + auto approxCurve = args.asMatPtr(2); + auto epsilon = args.asNumber(3); + auto closed = args.asBool(4); + + if(args.isMat(1)) { + auto curve = args.asMatPtr(1); + cv::approxPolyDP(*curve, *approxCurve, epsilon, closed); + } else { + auto curve = args.asMatVectorPtr(1); + cv::approxPolyDP(*curve, *approxCurve, epsilon, closed); + } + } break; + case hashString("arcLength", 9): { + auto closed = args.asBool(2); + + if(args.isMat(1)) { + auto curve = args.asMatPtr(1); + auto result = cv::arcLength(*curve, closed); + value.setProperty(runtime, "value", jsi::Value(result)); + } else { + auto curve = args.asMatVectorPtr(1); + auto result = cv::arcLength(*curve, closed); + value.setProperty(runtime, "value", jsi::Value(result)); + } + } break; + case hashString("boundingRect", 12): { + cv::Rect rect; + + if(args.isMat(1)) { + rect = cv::boundingRect(*args.asMatPtr(1)); + } else if(args.isMatVector(1)) { + rect = cv::boundingRect(*args.asMatVectorPtr(1)); + } else { + rect = cv::boundingRect(*args.asPointVectorPtr(1)); + } + + std::string id = FOCV_Storage::save(rect); + + return FOCV_JsiObject::wrap(runtime, "rect", id); + } break; + case hashString("connectedComponents", 19): { + auto image = args.asMatPtr(1); + auto labels = args.asMatPtr(2); + + auto result = cv::connectedComponents(*image, *labels); + value.setProperty(runtime, "value", jsi::Value(result)); + } break; + case hashString("connectedComponentsWithStats", 28): { + auto image = args.asMatPtr(1); + auto labels = args.asMatPtr(2); + auto stats = args.asMatPtr(3); + auto centroids = args.asMatPtr(4); + + auto result = cv::connectedComponentsWithStats(*image, *labels, *stats, *centroids); + value.setProperty(runtime, "value", jsi::Value(result)); + } break; + case hashString("contourArea", 11): { + auto oriented = args.asBool(2); + + if(args.isMat(1)) { + auto src = args.asMatPtr(1); + value.setProperty(runtime, "value", contourArea(*src, oriented)); + } else { + auto src = args.asPointVectorPtr(1); + value.setProperty(runtime, "value", contourArea(*src, oriented)); + } + } break; + case hashString("convexHull", 10): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + + cv::convexHull(*src, *dst); + } break; + case hashString("convexityDefects", 16): { + auto contour = args.asMatPtr(1); + auto convexHull = args.asMatPtr(2); + auto convexityDefects = args.asMatPtr(3); + + cv::convexityDefects(*contour, *convexHull, *convexityDefects); + } break; + case hashString("findContours", 12): { + auto src = args.asMatPtr(1); + auto mode = args.asNumber(3); + auto method = args.asNumber(4); + + if(args.isMatVector(2)) { + auto dst = args.asMatVectorPtr(2); + cv::findContours(*src, *dst, mode, method); + } else { + auto dst = args.asPointVectorOfVectorsPtr(2); + cv::findContours(*src, *dst, mode, method); + } + } break; + case hashString("fitLine", 7): { + auto points = args.asMatPtr(1); + auto line = args.asMatPtr(2); + auto disType = args.asNumber(3); + auto param = args.asNumber(4); + auto reps = args.asNumber(5); + auto aeps = args.asNumber(6); + + cv::fitLine(*points, *line, disType, param, reps, aeps); + } break; + case hashString("isContourConvex", 15): { + auto contour = args.asMatPtr(1); + + value.setProperty(runtime, "value", jsi::Value(cv::isContourConvex(*contour))); + } break; + case hashString("matchShapes", 11): { + auto contour1 = args.asMatPtr(1); + auto contour2 = args.asMatPtr(2); + auto method = args.asNumber(3); + auto parameter = args.asNumber(4); + + auto result = cv::matchShapes(*contour1, *contour2, method, parameter); + value.setProperty(runtime, "value", jsi::Value(result)); + } break; + case hashString("minAreaRect", 11): { + auto src = args.asMatPtr(1); + + auto rect = cv::minAreaRect(*src); + + auto id = FOCV_Storage::save(rect); + return FOCV_JsiObject::wrap(runtime, "rotated_rect", id); + } break; + case hashString("convertTo", 9): { + auto src = args.asMatPtr(1); + auto dst = args.asMatPtr(2); + auto rtype = args.asNumber(3); + + (*src).convertTo(*dst, rtype); + } break; } + } catch (cv::Exception& e) { + std::cout << "Fast OpenCV Invoke Error: " << e.what() << "\n"; + } - return value; + return value; } From 3cf555b3655050bd9abe572c5278f199f57eedb8 Mon Sep 17 00:00:00 2001 From: Thomas Coldwell <31568400+thomas-coldwell@users.noreply.github.com> Date: Thu, 12 Sep 2024 10:24:18 +0100 Subject: [PATCH 3/4] fix: frame memory deallocation issue --- cpp/react-native-fast-opencv.cpp | 25 +++++++++-- example/src/examples/CameraPassthrough.tsx | 6 +-- .../src/examples/CameraRealtimeDetection.tsx | 2 +- src/utils/UtilsFunctions.ts | 41 +++++++++++++++---- 4 files changed, 59 insertions(+), 15 deletions(-) diff --git a/cpp/react-native-fast-opencv.cpp b/cpp/react-native-fast-opencv.cpp index b49d369..562d426 100644 --- a/cpp/react-native-fast-opencv.cpp +++ b/cpp/react-native-fast-opencv.cpp @@ -41,15 +41,34 @@ jsi::Value OpenCVPlugin::get(jsi::Runtime& runtime, const jsi::PropNameID& propN if (propName == "frameBufferToMat") { return jsi::Function::createFromHostFunction( - runtime, jsi::PropNameID::forAscii(runtime, "frameBufferToMat"), 1, + runtime, jsi::PropNameID::forAscii(runtime, "frameBufferToMat"), 4, [=](jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments, size_t count) -> jsi::Object { + double rows = arguments[0].asNumber(); + double cols = arguments[1].asNumber(); + int channels = arguments[2].asNumber(); + jsi::Object input = arguments[3].asObject(runtime); + + int type = -1; + if (channels == 1) { + type = CV_8U; + } + if (channels == 3) { + type = CV_8UC3; + } + if (channels == 4) { + type = CV_8UC4; + } + + if (channels == -1) { + throw std::runtime_error("Fast OpenCV Error: Invalid channel count passed to frameBufferToMat!"); + } - jsi::Object input = arguments[2].asObject(runtime); TypedArrayBase inputBuffer = getTypedArray(runtime, std::move(input)); auto vec = inputBuffer.toVector(runtime); - cv::Mat mat(arguments[0].asNumber(), arguments[1].asNumber(), CV_8UC3, vec.data()); + cv::Mat mat(rows, cols, type); + memcpy(mat.data, vec.data(), (int)rows * (int)cols * channels); auto id = FOCV_Storage::save(mat); return FOCV_JsiObject::wrap(runtime, "mat", id); diff --git a/example/src/examples/CameraPassthrough.tsx b/example/src/examples/CameraPassthrough.tsx index 8f4e9d2..591e3de 100644 --- a/example/src/examples/CameraPassthrough.tsx +++ b/example/src/examples/CameraPassthrough.tsx @@ -130,9 +130,9 @@ export function CameraPassthrough() { rotation: '90deg', }); - // const frameMat = OpenCV.frameBufferToMat(HEIGHT, WIDTH, resized); - // const output = OpenCV.matToBuffer(frameMat, 'uint8'); - const data = Skia.Data.fromBytes(resized); + const frameMat = OpenCV.frameBufferToMat(HEIGHT, WIDTH, 4, resized); + const output = OpenCV.matToBuffer(frameMat, 'uint8'); + const data = Skia.Data.fromBytes(output.buffer); updatePreviewImageFromData(data, TARGET_FORMAT).then(() => { data.dispose(); diff --git a/example/src/examples/CameraRealtimeDetection.tsx b/example/src/examples/CameraRealtimeDetection.tsx index e99750a..cbdb078 100644 --- a/example/src/examples/CameraRealtimeDetection.tsx +++ b/example/src/examples/CameraRealtimeDetection.tsx @@ -47,7 +47,7 @@ export function CameraRealtimeDetection() { dataType: 'uint8', }); - const src = OpenCV.frameBufferToMat(height, width, resized); + const src = OpenCV.frameBufferToMat(height, width, 3, resized); const dst = OpenCV.createObject(ObjectType.Mat, 0, 0, DataTypes.CV_8U); const lowerBound = OpenCV.createObject(ObjectType.Scalar, 30, 60, 60); diff --git a/src/utils/UtilsFunctions.ts b/src/utils/UtilsFunctions.ts index adff942..d2fac63 100644 --- a/src/utils/UtilsFunctions.ts +++ b/src/utils/UtilsFunctions.ts @@ -1,15 +1,40 @@ import type { Mat } from '../objects/Objects'; export type UtilsFunctions = { + /** + * Clears any buffers that were allocate to back Mats on the native side. + */ clearBuffers(): void; - frameBufferToMat(rows: number, cols: number, input: Uint8Array): Mat; + /** + * Converts a byte array to a Mat. + * @param rows - the number of rows in the Mat + * @param cols - the number of columns in the Mat + * @param channels - the number of channels in the Mat + * @param input - the byte array to convert + */ + frameBufferToMat( + rows: number, + cols: number, + channels: number, + input: Uint8Array + ): Mat; + /** + * Converts a base64 string to a Mat. + * @param data - the base64 string to convert + */ base64ToMat(data: string): Mat; - matToBuffer( + /** + * Converts a Mat to a byte array. + * @param mat - the Mat to convert + * @param type - the type of the buffer to return ('uint8' or 'float32') + */ + matToBuffer( mat: Mat, - type: 'uint8' - ): { cols: number; rows: number; channels: number; buffer: Uint8Array }; - matToBuffer( - mat: Mat, - type: 'float32' - ): { cols: number; rows: number; channels: number; buffer: Float32Array }; + type: T + ): { + cols: number; + rows: number; + channels: number; + buffer: T extends 'uint8' ? Uint8Array : Float32Array; + }; }; From a3b8cf9c8ab4ff668c7635475cd267ca618b25a5 Mon Sep 17 00:00:00 2001 From: Thomas Coldwell <31568400+thomas-coldwell@users.noreply.github.com> Date: Thu, 12 Sep 2024 10:33:11 +0100 Subject: [PATCH 4/4] fix: revert development team --- example/ios/FastOpencvExample.xcodeproj/project.pbxproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/example/ios/FastOpencvExample.xcodeproj/project.pbxproj b/example/ios/FastOpencvExample.xcodeproj/project.pbxproj index 1221408..38614c1 100644 --- a/example/ios/FastOpencvExample.xcodeproj/project.pbxproj +++ b/example/ios/FastOpencvExample.xcodeproj/project.pbxproj @@ -472,7 +472,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = TFP6882UUN; + DEVELOPMENT_TEAM = PCT6GL3GWD; ENABLE_BITCODE = NO; INFOPLIST_FILE = FastOpencvExample/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -500,7 +500,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = TFP6882UUN; + DEVELOPMENT_TEAM = PCT6GL3GWD; INFOPLIST_FILE = FastOpencvExample/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)",