├── .gitattributes ├── .gitignore ├── .vscode └── settings.json ├── README.md ├── android ├── .project ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── io │ └── pickupp │ └── recatnativeopencv │ ├── RNOpenCVModule.java │ └── RNOpenCVPackage.java ├── index.js ├── ios ├── PrefixHeader.pch ├── RNOpenCV.h ├── RNOpenCV.mm ├── RNOpenCV.xcodeproj │ └── project.pbxproj └── RNOpenCV.xcworkspace │ └── contents.xcworkspacedata ├── package.json └── react-native-opencv.podspec /.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # OSX 3 | # 4 | .DS_Store 5 | 6 | # node.js 7 | # 8 | node_modules/ 9 | npm-debug.log 10 | yarn-error.log 11 | 12 | 13 | # Xcode 14 | # 15 | build/ 16 | *.pbxuser 17 | !default.pbxuser 18 | *.mode1v3 19 | !default.mode1v3 20 | *.mode2v3 21 | !default.mode2v3 22 | *.perspectivev3 23 | !default.perspectivev3 24 | xcuserdata 25 | *.xccheckout 26 | *.moved-aside 27 | DerivedData 28 | *.hmap 29 | *.ipa 30 | *.xcuserstate 31 | project.xcworkspace 32 | 33 | 34 | # Android/IntelliJ 35 | # 36 | build/ 37 | .idea 38 | .gradle 39 | local.properties 40 | *.iml 41 | 42 | # BUCK 43 | buck-out/ 44 | \.buckd/ 45 | *.keystore 46 | 47 | # gradle 48 | gradlew 49 | gradlew.bat 50 | import-summary.txt 51 | gradle/ 52 | *.so 53 | *.zip 54 | 55 | # sdk 56 | android/libraries/opencv/src/main/java 57 | android/libraries/opencv/src/main/res 58 | android/libraries/opencv/src/main/AndroidManifest.xml 59 | .settings -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "java.configuration.updateBuildConfiguration": "automatic" 3 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # @pickupp/react-native-opencv 3 | 4 | ## Getting started 5 | 6 | `$ npm install @pickupp/react-native-opencv --save` 7 | 8 | ### Mostly automatic installation 9 | 10 | `$ react-native link @pickupp/react-native-opencv` 11 | 12 | ### Prerequisite 13 | 14 | You can directly install the package but it will take a while for downloading the sdk required, 15 | you can download the sdk first and create a enviornment variable `export OPENCV_ANDROID_SDK=/path/to/sdk` 16 | 17 | ### Manual installation 18 | 19 | 20 | #### iOS 21 | 22 | # RN <0.60 23 | 24 | 1. In XCode, in the project navigator, right click `Libraries` ➜ `Add Files to [your project's name]` 25 | 2. Go to `node_modules` ➜ `@pickupp/react-native-opencv` and add `RNOpenCV.xcodeproj` 26 | 3. In XCode, in the project navigator, select your project. Add `libRNOpenCV.a` to your project's `Build Phases` ➜ `Link Binary With Libraries` 27 | 4. Run your project (`Cmd+R`) 28 | 29 | #### Android 30 | 31 | # RN >= 0.60 32 | 33 | 1. Open up `android/app/src/main/java/[...]/MainActivity.java` 34 | - Add 35 | ``` 36 | import org.opencv.android.BaseLoaderCallback; 37 | import org.opencv.android.LoaderCallbackInterface; 38 | import org.opencv.android.OpenCVLoader; 39 | ``` 40 | - Add 41 | ``` 42 | private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) { 43 | @Override 44 | public void onManagerConnected(int status) { 45 | switch (status) { 46 | case LoaderCallbackInterface.SUCCESS: 47 | { 48 | Log.i("OpenCV", "OpenCV loaded successfully"); 49 | } break; 50 | default: 51 | { 52 | super.onManagerConnected(status); 53 | } break; 54 | } 55 | } 56 | }; 57 | 58 | public void onCreate() { 59 | super.onCreate(); 60 | if (!OpenCVLoader.initDebug()) { 61 | Log.d("OpenCv", "Error while init"); 62 | } 63 | } 64 | 65 | public void onResume() 66 | { 67 | if (!OpenCVLoader.initDebug()) { 68 | Log.d("OpenCV", "Internal OpenCV library not found. Using OpenCV Manager for initialization"); 69 | OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this, mLoaderCallback); 70 | } else { 71 | Log.d("OpenCV", "OpenCV library found inside package. Using it!"); 72 | mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS); 73 | } 74 | } 75 | ``` 76 | 2. Insert the following lines inside the dependencies block in `android/build.gradle` under `allProjects -> dependencies`: 77 | ``` 78 | maven { 79 | url "https://dl.bintray.com/pickuppdev/pickupp" 80 | } 81 | ``` 82 | 83 | 3. Insert the following lines inside the dependencies block in `android/app/build.gradle` under `allProjects -> dependencies`: 84 | ``` 85 | implementation 'org.opencv.android:opencv-android-sdk:3.4.+' 86 | ``` 87 | 88 | # RN < 0.60 89 | 90 | 1. Open up `android/app/src/main/java/[...]/MainActivity.java` 91 | - Add `import io.pickupp.recatnativeopencv.RNOpenCVPackage;` to the imports at the top of the file 92 | - Add `new RNOpenCVPackage()` to the list returned by the `getPackages()` method 93 | - Add 94 | ``` 95 | import org.opencv.android.BaseLoaderCallback; 96 | import org.opencv.android.LoaderCallbackInterface; 97 | import org.opencv.android.OpenCVLoader; 98 | ``` 99 | - Add 100 | ``` 101 | private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) { 102 | @Override 103 | public void onManagerConnected(int status) { 104 | switch (status) { 105 | case LoaderCallbackInterface.SUCCESS: 106 | { 107 | Log.i("OpenCV", "OpenCV loaded successfully"); 108 | } break; 109 | default: 110 | { 111 | super.onManagerConnected(status); 112 | } break; 113 | } 114 | } 115 | }; 116 | 117 | public void onCreate() { 118 | super.onCreate(); 119 | if (!OpenCVLoader.initDebug()) { 120 | Log.d("OpenCv", "Error while init"); 121 | } 122 | } 123 | 124 | public void onResume() 125 | { 126 | if (!OpenCVLoader.initDebug()) { 127 | Log.d("OpenCV", "Internal OpenCV library not found. Using OpenCV Manager for initialization"); 128 | OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this, mLoaderCallback); 129 | } else { 130 | Log.d("OpenCV", "OpenCV library found inside package. Using it!"); 131 | mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS); 132 | } 133 | } 134 | ``` 135 | 2. Append the following lines to `android/settings.gradle`: 136 | ``` 137 | include ':react-native-opencv' 138 | project(':react-native-opencv').projectDir = new File(rootProject.projectDir, '../node_modules/@pickupp/react-native-opencv/android') 139 | include ':opencv-android-sdk' 140 | project(':opencv-android-sdk').projectDir = new File(rootProject.projectDir, '../node_modules/@pickupp/react-native-opencv/android/libraries/opencv') 141 | ``` 142 | 3. Insert the following lines inside the dependencies block in `android/app/build.gradle`: 143 | ``` 144 | implementation project(':react-native-opencv') 145 | implementation project(':opencv-android-sdk') 146 | ``` 147 | 4. Insert the following lines inside the android block `andriod/app/build.gradle` 148 | ``` 149 | sourceSets.main { 150 | // include opencv native jni 151 | jniLibs.srcDir '../../node_modules/@pickupp/react-native-opencv/android/libraries/opencv/jniLibs' 152 | jni.srcDirs = [] //disable automatic ndk-build call 153 | } 154 | ``` 155 | 156 | ## Usage 157 | ```javascript 158 | import RNOpenCV from '@pickupp/react-native-opencv'; 159 | 160 | const maxEdgeLength = await RNOpenCV.findMaxEdge(/* base64ImageString */) 161 | const laplacianScore = await RNOpenCV.laplacianBlurryCheck(/* base64ImageString */) 162 | ``` 163 | 164 | -------------------------------------------------------------------------------- /android/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | android 4 | Project android created by Buildship. 5 | 6 | 7 | 8 | 9 | org.eclipse.buildship.core.gradleprojectbuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.buildship.core.gradleprojectnature 16 | 17 | 18 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | 2 | buildscript { 3 | repositories { 4 | jcenter() 5 | } 6 | 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:1.3.1' 9 | } 10 | } 11 | 12 | apply plugin: 'com.android.library' 13 | 14 | android { 15 | compileSdkVersion 27 16 | buildToolsVersion "27.0.3" 17 | 18 | defaultConfig { 19 | minSdkVersion 16 20 | targetSdkVersion 27 21 | } 22 | lintOptions { 23 | abortOnError false 24 | } 25 | } 26 | 27 | repositories { 28 | mavenCentral() 29 | } 30 | 31 | dependencies { 32 | implementation 'com.facebook.react:react-native:+' 33 | implementation 'org.opencv.android:opencv-android-sdk:3.4.+' 34 | } 35 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /android/src/main/java/io/pickupp/recatnativeopencv/RNOpenCVModule.java: -------------------------------------------------------------------------------- 1 | package io.pickupp.recatnativeopencv; 2 | 3 | import com.facebook.react.bridge.ReactApplicationContext; 4 | import com.facebook.react.bridge.ReactContextBaseJavaModule; 5 | import com.facebook.react.bridge.ReactMethod; 6 | import com.facebook.react.bridge.Promise; 7 | 8 | import java.util.List; 9 | import java.util.ArrayList; 10 | 11 | import android.graphics.Bitmap; 12 | import android.graphics.BitmapFactory; 13 | 14 | import org.opencv.core.CvType; 15 | import org.opencv.core.Mat; 16 | import org.opencv.core.MatOfPoint; 17 | import org.opencv.core.MatOfPoint2f; 18 | import org.opencv.core.Size; 19 | import org.opencv.core.Point; 20 | import org.opencv.android.Utils; 21 | import org.opencv.imgproc.Imgproc; 22 | 23 | import android.util.Base64; 24 | 25 | public class RNOpenCVModule extends ReactContextBaseJavaModule { 26 | 27 | private final ReactApplicationContext reactContext; 28 | 29 | public RNOpenCVModule(ReactApplicationContext reactContext) { 30 | super(reactContext); 31 | this.reactContext = reactContext; 32 | } 33 | 34 | @Override 35 | public String getName() { 36 | return "RNOpenCV"; 37 | } 38 | 39 | public Mat imageBase64ToMat(String imageAsBase64) { 40 | BitmapFactory.Options options = new BitmapFactory.Options(); 41 | options.inDither = true; 42 | options.inPreferredConfig = Bitmap.Config.ARGB_8888; 43 | 44 | byte[] decodedString = Base64.decode(imageAsBase64, Base64.DEFAULT); 45 | Bitmap image = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length); 46 | Mat matImage = new Mat(); 47 | Utils.bitmapToMat(image, matImage); 48 | 49 | return matImage; 50 | } 51 | 52 | @ReactMethod 53 | public void laplacianBlurryCheck(String imageAsBase64, Promise promise) { 54 | try { 55 | // https://stackoverflow.com/questions/36862451/opencv-with-laplacian-formula-to-detect-image-is-blur-or-not-in-android 56 | Mat matImage = this.imageBase64ToMat(imageAsBase64); 57 | int l = CvType.CV_8UC1; //8-bit grey scale image 58 | Mat matImageGrey = new Mat(); 59 | Imgproc.cvtColor(matImage, matImageGrey, Imgproc.COLOR_BGR2GRAY); 60 | 61 | Mat laplacianImage = new Mat(); 62 | matImage.convertTo(laplacianImage, l); 63 | Imgproc.Laplacian(matImageGrey, laplacianImage, CvType.CV_8U); 64 | Mat laplacianImage8bit = new Mat(); 65 | laplacianImage.convertTo(laplacianImage8bit, l); 66 | 67 | int size = (int)(laplacianImage8bit.elemSize() * laplacianImage8bit.total()); 68 | byte[] pixels = new byte[size]; 69 | laplacianImage8bit.get(0, 0, pixels); 70 | int maxLap = 0; 71 | for (byte pixel : pixels) { 72 | int value = pixel & 0xFF; 73 | if (value > maxLap) { 74 | maxLap = value; 75 | } 76 | } 77 | 78 | promise.resolve(maxLap); 79 | } catch (Exception e) { 80 | promise.reject("unable to calculate laplacian score", e); 81 | } 82 | } 83 | 84 | @ReactMethod 85 | public void findMaxEdge(String imageAsBase64, Promise promise) { 86 | try { 87 | Mat matImage = this.imageBase64ToMat(imageAsBase64); 88 | Mat matImageGrey = new Mat(); 89 | Imgproc.cvtColor(matImage, matImageGrey, Imgproc.COLOR_BGR2GRAY); 90 | Imgproc.GaussianBlur(matImageGrey, matImageGrey, new Size(9, 9), 2, 2); 91 | 92 | Mat canny = new Mat(); 93 | Imgproc.Canny(matImageGrey, canny, 50, 100, 3); 94 | List contours = new ArrayList<>(); 95 | Mat hierarchy = new Mat(); 96 | // Imgproc.CV_RETR_TREE: 3 97 | // CV_CHAIN_APPROX_NONE: 1 98 | Imgproc.findContours(canny, contours, hierarchy, 3, 1); 99 | 100 | double maxLength = 0; 101 | for (MatOfPoint edge : contours) { 102 | MatOfPoint2f newEdge = new MatOfPoint2f(edge.toArray()); 103 | double value = Imgproc.arcLength(newEdge, false); 104 | if (value > maxLength) { 105 | maxLength = value; 106 | } 107 | } 108 | 109 | promise.resolve(maxLength); 110 | } catch (Exception e) { 111 | promise.reject("unable to find max edge", e); 112 | } 113 | } 114 | 115 | // TODO: implement other methods 116 | } 117 | -------------------------------------------------------------------------------- /android/src/main/java/io/pickupp/recatnativeopencv/RNOpenCVPackage.java: -------------------------------------------------------------------------------- 1 | package io.pickupp.recatnativeopencv; 2 | 3 | import java.util.Arrays; 4 | import java.util.Collections; 5 | import java.util.List; 6 | 7 | import com.facebook.react.ReactPackage; 8 | import com.facebook.react.bridge.NativeModule; 9 | import com.facebook.react.bridge.ReactApplicationContext; 10 | import com.facebook.react.uimanager.ViewManager; 11 | import com.facebook.react.bridge.JavaScriptModule; 12 | public class RNOpenCVPackage implements ReactPackage { 13 | @Override 14 | public List createNativeModules(ReactApplicationContext reactContext) { 15 | return Arrays.asList(new RNOpenCVModule(reactContext)); 16 | } 17 | 18 | // Deprecated from RN 0.47 19 | public List> createJSModules() { 20 | return Collections.emptyList(); 21 | } 22 | 23 | @Override 24 | public List createViewManagers(ReactApplicationContext reactContext) { 25 | return Collections.emptyList(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import { NativeModules } from 'react-native' 2 | 3 | export default NativeModules.RNOpenCV 4 | -------------------------------------------------------------------------------- /ios/PrefixHeader.pch: -------------------------------------------------------------------------------- 1 | #ifndef PrefixHeader_pch 2 | #define PrefixHeader_pch 3 | 4 | #ifdef __cplusplus 5 | #import 6 | #endif 7 | 8 | #endif -------------------------------------------------------------------------------- /ios/RNOpenCV.h: -------------------------------------------------------------------------------- 1 | #if __has_include("RCTBridgeModule.h") 2 | #import "RCTBridgeModule.h" 3 | #else 4 | #import 5 | #endif 6 | 7 | #import 8 | 9 | @interface RNOpenCV : NSObject 10 | 11 | @end 12 | -------------------------------------------------------------------------------- /ios/RNOpenCV.mm: -------------------------------------------------------------------------------- 1 | #import "RNOpenCV.h" 2 | #import 3 | #import 4 | #import 5 | #import 6 | #import 7 | 8 | @implementation RNOpenCV 9 | 10 | - (dispatch_queue_t)methodQueue { 11 | return dispatch_get_main_queue(); 12 | } 13 | RCT_EXPORT_MODULE() 14 | 15 | RCT_EXPORT_METHOD(laplacianBlurryCheck 16 | : (NSString *)imageAsBase64 resolver 17 | : (RCTPromiseResolveBlock)resolve rejecter 18 | : (RCTPromiseRejectBlock)reject) { 19 | @try { 20 | UIImage *image = [self decodeBase64ToImage:imageAsBase64]; 21 | 22 | UInt8 laplacianScore = [self laplacianBlurryCheck:image]; 23 | 24 | resolve([NSNumber numberWithInt:laplacianScore]); 25 | } @catch (NSException *exception) { 26 | NSError *error; 27 | reject(@"error", exception.reason, error); 28 | } 29 | } 30 | 31 | RCT_EXPORT_METHOD(tenengradBlurryCheck 32 | : (NSString *)imageAsBase64 resolver 33 | : (RCTPromiseResolveBlock)resolve rejecter 34 | : (RCTPromiseRejectBlock)reject) { 35 | NSError *error; 36 | UIImage *image = [self decodeBase64ToImage:imageAsBase64]; 37 | 38 | int tenengradScore = [self tenengradBlurryCheck:image]; 39 | 40 | if (tenengradScore) { 41 | resolve([NSNumber numberWithDouble:tenengradScore]); 42 | } else { 43 | reject(@"invaild_score", @"Cannot calculate tenegrad score", error); 44 | } 45 | } 46 | 47 | RCT_EXPORT_METHOD(brennerBlurryCheck 48 | : (NSString *)imageAsBase64 resolver 49 | : (RCTPromiseResolveBlock)resolve rejecter 50 | : (RCTPromiseRejectBlock)reject) { 51 | NSError *error; 52 | UIImage *image = [self decodeBase64ToImage:imageAsBase64]; 53 | 54 | int brennerScore = [self brennerBlurryCheck:image]; 55 | 56 | if (brennerScore) { 57 | resolve([NSNumber numberWithFloat:brennerScore]); 58 | } else { 59 | reject(@"invaild_score", @"Cannot calculate brenner score", error); 60 | } 61 | } 62 | 63 | RCT_EXPORT_METHOD(stdevBlurryCheck 64 | : (NSString *)imageAsBase64 resolver 65 | : (RCTPromiseResolveBlock)resolve rejecter 66 | : (RCTPromiseRejectBlock)reject) { 67 | NSError *error; 68 | UIImage *image = [self decodeBase64ToImage:imageAsBase64]; 69 | 70 | int stdevScore = [self stdevBlurryCheck:image]; 71 | 72 | if (stdevScore) { 73 | resolve([NSNumber numberWithDouble:stdevScore]); 74 | } else { 75 | reject(@"invaild_score", @"Cannot calculate stdev score", error); 76 | } 77 | } 78 | 79 | RCT_EXPORT_METHOD(entropyBlurryCheck 80 | : (NSString *)imageAsBase64 resolver 81 | : (RCTPromiseResolveBlock)resolve rejecter 82 | : (RCTPromiseRejectBlock)reject) { 83 | NSError *error; 84 | UIImage *image = [self decodeBase64ToImage:imageAsBase64]; 85 | 86 | int entropyScore = [self entropyBlurryCheck:image]; 87 | 88 | if (entropyScore) { 89 | resolve([NSNumber numberWithDouble:entropyScore]); 90 | } else { 91 | reject(@"invaild_score", @"Cannot calculate entropy score", error); 92 | } 93 | } 94 | 95 | RCT_EXPORT_METHOD(findMaxEdge 96 | : (NSString *)imageAsBase64 resolver 97 | : (RCTPromiseResolveBlock)resolve rejecter 98 | : (RCTPromiseRejectBlock)reject) { 99 | @try { 100 | UIImage *image = [self decodeBase64ToImage:imageAsBase64]; 101 | cv::Mat matImage = [self convertUIImageToCVMat:image]; 102 | 103 | double laplacianScore = [self findMaxEdge:&matImage]; 104 | 105 | resolve([NSNumber numberWithDouble:laplacianScore]); 106 | } @catch (NSException *exception) { 107 | NSError *error; 108 | reject(@"error", exception.reason, error); 109 | } 110 | } 111 | 112 | // native code 113 | - (NSString *)imageToNSString:(UIImage *)image { 114 | NSData *imageData = UIImagePNGRepresentation(image); 115 | 116 | return [imageData 117 | base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength]; 118 | } 119 | - (cv::Mat)convertUIImageToCVMat:(UIImage *)image { 120 | CGColorSpaceRef colorSpace = CGImageGetColorSpace(image.CGImage); 121 | CGFloat cols = image.size.width; 122 | CGFloat rows = image.size.height; 123 | 124 | cv::Mat cvMat( 125 | rows, cols, 126 | CV_8UC4); // 8 bits per component, 4 channels (color channels + alpha) 127 | 128 | CGContextRef contextRef = 129 | CGBitmapContextCreate(cvMat.data, // Pointer to data 130 | cols, // Width of bitmap 131 | rows, // Height of bitmap 132 | 8, // Bits per component 133 | cvMat.step[0], // Bytes per row 134 | colorSpace, // Colorspace 135 | kCGImageAlphaNoneSkipLast | 136 | kCGBitmapByteOrderDefault); // Bitmap info flags 137 | 138 | CGContextDrawImage(contextRef, CGRectMake(0, 0, cols, rows), image.CGImage); 139 | CGContextRelease(contextRef); 140 | 141 | return cvMat; 142 | } 143 | 144 | - (UIImage *)decodeBase64ToImage:(NSString *)strEncodeData { 145 | NSData *data = [[NSData alloc] 146 | initWithBase64EncodedString:strEncodeData 147 | options:NSDataBase64DecodingIgnoreUnknownCharacters]; 148 | return [UIImage imageWithData:data]; 149 | } 150 | 151 | - (UInt8)laplacianBlurryCheck:(UIImage *)image { 152 | // converting UIImage to OpenCV format - Mat 153 | cv::Mat matImage = [self convertUIImageToCVMat:image]; 154 | cv::Mat matImageGrey; 155 | // converting image's color space (RGB) to grayscale 156 | cv::cvtColor(matImage, matImageGrey, CV_BGR2GRAY); 157 | 158 | cv::Mat laplacianImage; 159 | matImage.convertTo(laplacianImage, CV_8UC1); 160 | 161 | // applying Laplacian operator to the image 162 | cv::Laplacian(matImageGrey, laplacianImage, CV_8U); 163 | cv::Mat laplacianImage8bit; 164 | laplacianImage.convertTo(laplacianImage8bit, CV_8UC1); 165 | 166 | unsigned char *pixels = laplacianImage8bit.data; 167 | 168 | // 16777216 = 256*256*256 169 | UInt8 maxLap = 0; 170 | for (int i = 0; 171 | i < (laplacianImage8bit.elemSize() * laplacianImage8bit.total()); i++) { 172 | if (pixels[i] > maxLap) { 173 | maxLap = pixels[i]; 174 | } 175 | } 176 | // one of the main parameters here: threshold sets the sensitivity for the 177 | // blur check smaller number = less sensitive; default = 180 178 | 179 | return maxLap; 180 | } 181 | 182 | - (UInt8)laplacianProcess:(cv::Mat *)matImage 183 | laplacianImage:(cv::Mat *)singleChannel { 184 | cv::Mat laplacianImage; 185 | matImage->convertTo(laplacianImage, CV_8UC1); 186 | 187 | // applying Laplacian operator to the image 188 | cv::Laplacian(*singleChannel, laplacianImage, CV_8U); 189 | cv::Mat laplacianImageBlue; 190 | laplacianImage.convertTo(laplacianImageBlue, CV_8UC1); 191 | 192 | unsigned char *bluePixels = laplacianImageBlue.data; 193 | 194 | UInt8 maxLap = 0; 195 | for (int i = 0; i < (singleChannel->elemSize() * singleChannel->total()); 196 | i++) { 197 | if (bluePixels[i] > maxLap) { 198 | maxLap = bluePixels[i]; 199 | } 200 | } 201 | return maxLap; 202 | } 203 | 204 | - (double)tenengradBlurryCheck:(UIImage *)image { 205 | // converting UIImage to OpenCV format - Mat 206 | cv::Mat matImage = [self convertUIImageToCVMat:image]; 207 | cv::Mat matImageGrey; 208 | // converting image's color space (RGB) to grayscale 209 | cv::cvtColor(matImage, matImageGrey, CV_BGR2GRAY); 210 | 211 | cv::Mat imageSobel; 212 | Sobel(matImageGrey, imageSobel, CV_16U, 1, 1); 213 | double meanValue = 0.0; 214 | meanValue = mean(imageSobel)[0]; 215 | 216 | return meanValue; 217 | } 218 | 219 | - (float)brennerBlurryCheck:(UIImage *)image { 220 | // converting UIImage to OpenCV format - Mat 221 | cv::Mat matImage = [self convertUIImageToCVMat:image]; 222 | cv::Mat matImageGrey; 223 | // converting image's color space (RGB) to grayscale 224 | cv::cvtColor(matImage, matImageGrey, CV_BGR2GRAY); 225 | 226 | // Brenner's Algorithm 227 | 228 | cv::Size s = matImageGrey.size(); 229 | int rows = s.height; 230 | int cols = s.width; 231 | cv::Mat DH = cv::Mat(rows, cols, CV_64F, double(0)); 232 | cv::Mat DV = cv::Mat(rows, cols, CV_64F, double(0)); 233 | cv::subtract(matImageGrey.rowRange(2, rows).colRange(0, cols), 234 | matImageGrey.rowRange(0, rows - 2).colRange(0, cols), 235 | DV.rowRange(0, rows - 2).colRange(0, cols)); 236 | cv::subtract(matImageGrey.rowRange(0, rows).colRange(2, cols), 237 | matImageGrey.rowRange(0, rows).colRange(0, cols - 2), 238 | DH.rowRange(0, rows).colRange(0, cols - 2)); 239 | 240 | cv::Mat FM = cv::max(DH, DV); 241 | FM = FM.mul(FM); 242 | cv::Scalar tempVal = mean(FM); 243 | float myMatMean = tempVal.val[0]; 244 | return myMatMean; 245 | } 246 | 247 | - (double)stdevBlurryCheck:(UIImage *)image { 248 | // converting UIImage to OpenCV format - Mat 249 | cv::Mat matImage = [self convertUIImageToCVMat:image]; 250 | cv::Mat matImageGrey; 251 | // converting image's color space (RGB) to grayscale 252 | cv::cvtColor(matImage, matImageGrey, CV_BGR2GRAY); 253 | 254 | cv::Mat meanValueImage; 255 | cv::Mat meanStdValueImage; 256 | meanStdDev(matImageGrey, meanValueImage, meanStdValueImage); 257 | double meanValue = 0.0; 258 | meanValue = meanStdValueImage.at(0, 0); 259 | 260 | return meanValue; 261 | } 262 | 263 | - (double)entropyBlurryCheck:(UIImage *)image { 264 | // converting UIImage to OpenCV format - Mat 265 | cv::Mat matImage = [self convertUIImageToCVMat:image]; 266 | // allocate memory 267 | double temp[256] = {0.0}; 268 | 269 | // calculate acc. value for each row 270 | for (int m = 0; m < matImage.rows; m++) { // look over cols 271 | const uchar *t = matImage.ptr(m); 272 | for (int n = 0; n < matImage.cols; n++) { 273 | int i = t[n]; 274 | temp[i] = temp[i] + 1; 275 | } 276 | } 277 | 278 | // calculate over pixels 279 | for (int i = 0; i < 256; i++) { 280 | temp[i] = temp[i] / (matImage.rows * matImage.cols); 281 | } 282 | 283 | double result = 0; 284 | // calculate logs 285 | for (int i = 0; i < 256; i++) { 286 | if (temp[i] == 0.0) 287 | result = result; 288 | else 289 | result = result - temp[i] * (log(temp[i]) / log(2.0)); 290 | } 291 | 292 | return result; 293 | } 294 | 295 | - (double)findMaxEdge:(cv::Mat *)matImage { 296 | // converting UIImage to OpenCV format - Mat 297 | cv::Mat matImageGrey; 298 | // converting image's color space (RGB) to grayscale 299 | cv::cvtColor(*matImage, matImageGrey, CV_BGR2GRAY); 300 | 301 | // This is done so as to prevent a lot of false circles from being detected 302 | cv::GaussianBlur(matImageGrey, matImageGrey, cv::Size(9, 9), 2, 2); 303 | 304 | cv::Mat canny = cv::Mat(matImage->size(), CV_8UC1); 305 | cv::Canny(matImageGrey, canny, 50, 100, 3); 306 | 307 | std::vector> contours; 308 | std::vector hierarchy; 309 | cv::findContours(canny, contours, hierarchy, CV_RETR_TREE, 310 | CV_CHAIN_APPROX_NONE); 311 | double maxLength = 0; 312 | 313 | for (int i = 0; i < contours.size(); i++) { 314 | double edgeLenght = cv::arcLength(contours[i], FALSE); 315 | if (edgeLenght > maxLength) { 316 | maxLength = edgeLenght; 317 | } 318 | } 319 | 320 | return maxLength; 321 | } 322 | 323 | @end 324 | -------------------------------------------------------------------------------- /ios/RNOpenCV.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | B3E7B58A1CC2AC0600A0062D /* RNOpenCV.mm in Sources */ = {isa = PBXBuildFile; fileRef = B3E7B5891CC2AC0600A0062D /* RNOpenCV.mm */; }; 11 | /* End PBXBuildFile section */ 12 | 13 | /* Begin PBXCopyFilesBuildPhase section */ 14 | 58B511D91A9E6C8500147676 /* CopyFiles */ = { 15 | isa = PBXCopyFilesBuildPhase; 16 | buildActionMask = 2147483647; 17 | dstPath = "include/$(PRODUCT_NAME)"; 18 | dstSubfolderSpec = 16; 19 | files = ( 20 | ); 21 | runOnlyForDeploymentPostprocessing = 0; 22 | }; 23 | /* End PBXCopyFilesBuildPhase section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | 134814201AA4EA6300B7C361 /* libRNOpenCV.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNOpenCV.a; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | B3E7B5881CC2AC0600A0062D /* RNOpenCV.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNOpenCV.h; sourceTree = ""; }; 28 | B3E7B5891CC2AC0600A0062D /* RNOpenCV.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNOpenCV.mm; sourceTree = ""; }; 29 | /* End PBXFileReference section */ 30 | 31 | /* Begin PBXFrameworksBuildPhase section */ 32 | 58B511D81A9E6C8500147676 /* Frameworks */ = { 33 | isa = PBXFrameworksBuildPhase; 34 | buildActionMask = 2147483647; 35 | files = ( 36 | ); 37 | runOnlyForDeploymentPostprocessing = 0; 38 | }; 39 | /* End PBXFrameworksBuildPhase section */ 40 | 41 | /* Begin PBXGroup section */ 42 | 134814211AA4EA7D00B7C361 /* Products */ = { 43 | isa = PBXGroup; 44 | children = ( 45 | 134814201AA4EA6300B7C361 /* libRNOpenCV.a */, 46 | ); 47 | name = Products; 48 | sourceTree = ""; 49 | }; 50 | 58B511D21A9E6C8500147676 = { 51 | isa = PBXGroup; 52 | children = ( 53 | B3E7B5881CC2AC0600A0062D /* RNOpenCV.h */, 54 | B3E7B5891CC2AC0600A0062D /* RNOpenCV.mm */, 55 | 134814211AA4EA7D00B7C361 /* Products */, 56 | ); 57 | sourceTree = ""; 58 | }; 59 | /* End PBXGroup section */ 60 | 61 | /* Begin PBXNativeTarget section */ 62 | 58B511DA1A9E6C8500147676 /* RNOpenCV */ = { 63 | isa = PBXNativeTarget; 64 | buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNOpenCV" */; 65 | buildPhases = ( 66 | 58B511D71A9E6C8500147676 /* Sources */, 67 | 58B511D81A9E6C8500147676 /* Frameworks */, 68 | 58B511D91A9E6C8500147676 /* CopyFiles */, 69 | ); 70 | buildRules = ( 71 | ); 72 | dependencies = ( 73 | ); 74 | name = RNOpenCV; 75 | productName = RCTDataManager; 76 | productReference = 134814201AA4EA6300B7C361 /* libRNOpenCV.a */; 77 | productType = "com.apple.product-type.library.static"; 78 | }; 79 | /* End PBXNativeTarget section */ 80 | 81 | /* Begin PBXProject section */ 82 | 58B511D31A9E6C8500147676 /* Project object */ = { 83 | isa = PBXProject; 84 | attributes = { 85 | LastUpgradeCheck = 1010; 86 | ORGANIZATIONNAME = Facebook; 87 | TargetAttributes = { 88 | 58B511DA1A9E6C8500147676 = { 89 | CreatedOnToolsVersion = 6.1.1; 90 | }; 91 | }; 92 | }; 93 | buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNOpenCV" */; 94 | compatibilityVersion = "Xcode 3.2"; 95 | developmentRegion = English; 96 | hasScannedForEncodings = 0; 97 | knownRegions = ( 98 | en, 99 | ); 100 | mainGroup = 58B511D21A9E6C8500147676; 101 | productRefGroup = 58B511D21A9E6C8500147676; 102 | projectDirPath = ""; 103 | projectRoot = ""; 104 | targets = ( 105 | 58B511DA1A9E6C8500147676 /* RNOpenCV */, 106 | ); 107 | }; 108 | /* End PBXProject section */ 109 | 110 | /* Begin PBXSourcesBuildPhase section */ 111 | 58B511D71A9E6C8500147676 /* Sources */ = { 112 | isa = PBXSourcesBuildPhase; 113 | buildActionMask = 2147483647; 114 | files = ( 115 | B3E7B58A1CC2AC0600A0062D /* RNOpenCV.mm in Sources */, 116 | ); 117 | runOnlyForDeploymentPostprocessing = 0; 118 | }; 119 | /* End PBXSourcesBuildPhase section */ 120 | 121 | /* Begin XCBuildConfiguration section */ 122 | 58B511ED1A9E6C8500147676 /* Debug */ = { 123 | isa = XCBuildConfiguration; 124 | buildSettings = { 125 | ALWAYS_SEARCH_USER_PATHS = NO; 126 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 127 | CLANG_CXX_LIBRARY = "libc++"; 128 | CLANG_ENABLE_MODULES = YES; 129 | CLANG_ENABLE_OBJC_ARC = YES; 130 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 131 | CLANG_WARN_BOOL_CONVERSION = YES; 132 | CLANG_WARN_COMMA = YES; 133 | CLANG_WARN_CONSTANT_CONVERSION = YES; 134 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 135 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 136 | CLANG_WARN_EMPTY_BODY = YES; 137 | CLANG_WARN_ENUM_CONVERSION = YES; 138 | CLANG_WARN_INFINITE_RECURSION = YES; 139 | CLANG_WARN_INT_CONVERSION = YES; 140 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 141 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 142 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 143 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 144 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 145 | CLANG_WARN_STRICT_PROTOTYPES = YES; 146 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 147 | CLANG_WARN_UNREACHABLE_CODE = YES; 148 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 149 | COPY_PHASE_STRIP = NO; 150 | ENABLE_STRICT_OBJC_MSGSEND = YES; 151 | ENABLE_TESTABILITY = YES; 152 | GCC_C_LANGUAGE_STANDARD = gnu99; 153 | GCC_DYNAMIC_NO_PIC = NO; 154 | GCC_INPUT_FILETYPE = sourcecode.cpp.objcpp; 155 | GCC_NO_COMMON_BLOCKS = YES; 156 | GCC_OPTIMIZATION_LEVEL = 0; 157 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 158 | GCC_PREFIX_HEADER = "$(PROJECT_DIR)/PrefixHeader.pch"; 159 | GCC_PREPROCESSOR_DEFINITIONS = ( 160 | "DEBUG=1", 161 | "$(inherited)", 162 | ); 163 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 164 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 165 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 166 | GCC_WARN_UNDECLARED_SELECTOR = YES; 167 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 168 | GCC_WARN_UNUSED_FUNCTION = YES; 169 | GCC_WARN_UNUSED_VARIABLE = YES; 170 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 171 | MTL_ENABLE_DEBUG_INFO = YES; 172 | ONLY_ACTIVE_ARCH = YES; 173 | SDKROOT = iphoneos; 174 | }; 175 | name = Debug; 176 | }; 177 | 58B511EE1A9E6C8500147676 /* Release */ = { 178 | isa = XCBuildConfiguration; 179 | buildSettings = { 180 | ALWAYS_SEARCH_USER_PATHS = NO; 181 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 182 | CLANG_CXX_LIBRARY = "libc++"; 183 | CLANG_ENABLE_MODULES = YES; 184 | CLANG_ENABLE_OBJC_ARC = YES; 185 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 186 | CLANG_WARN_BOOL_CONVERSION = YES; 187 | CLANG_WARN_COMMA = YES; 188 | CLANG_WARN_CONSTANT_CONVERSION = YES; 189 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 190 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 191 | CLANG_WARN_EMPTY_BODY = YES; 192 | CLANG_WARN_ENUM_CONVERSION = YES; 193 | CLANG_WARN_INFINITE_RECURSION = YES; 194 | CLANG_WARN_INT_CONVERSION = YES; 195 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 196 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 197 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 198 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 199 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 200 | CLANG_WARN_STRICT_PROTOTYPES = YES; 201 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 202 | CLANG_WARN_UNREACHABLE_CODE = YES; 203 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 204 | COPY_PHASE_STRIP = YES; 205 | ENABLE_NS_ASSERTIONS = NO; 206 | ENABLE_STRICT_OBJC_MSGSEND = YES; 207 | GCC_C_LANGUAGE_STANDARD = gnu99; 208 | GCC_INPUT_FILETYPE = sourcecode.cpp.objcpp; 209 | GCC_NO_COMMON_BLOCKS = YES; 210 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 211 | GCC_PREFIX_HEADER = "$(PROJECT_DIR)/PrefixHeader.pch"; 212 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 213 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 214 | GCC_WARN_UNDECLARED_SELECTOR = YES; 215 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 216 | GCC_WARN_UNUSED_FUNCTION = YES; 217 | GCC_WARN_UNUSED_VARIABLE = YES; 218 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 219 | MTL_ENABLE_DEBUG_INFO = NO; 220 | SDKROOT = iphoneos; 221 | VALIDATE_PRODUCT = YES; 222 | }; 223 | name = Release; 224 | }; 225 | 58B511F01A9E6C8500147676 /* Debug */ = { 226 | isa = XCBuildConfiguration; 227 | buildSettings = { 228 | DEAD_CODE_STRIPPING = NO; 229 | ENABLE_ON_DEMAND_RESOURCES = NO; 230 | FRAMEWORK_SEARCH_PATHS = ( 231 | "$(inherited)", 232 | "$(SRCROOT)/../../../ios/Pods", 233 | "$(SRCROOT)/../../../ios", 234 | "$(SRCROOT)/../../../ios/Pods/OpenCV/**", 235 | ); 236 | GCC_NO_COMMON_BLOCKS = YES; 237 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 238 | GCC_PREFIX_HEADER = "$(PROJECT_DIR)/PrefixHeader.pch"; 239 | GCC_PREPROCESSOR_DEFINITIONS = ( 240 | "DEBUG=1", 241 | "$(inherited)", 242 | ); 243 | GCC_VERSION = ""; 244 | HEADER_SEARCH_PATHS = ( 245 | "$(inherited)", 246 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 247 | "$(SRCROOT)/../../../React/**", 248 | "$(SRCROOT)/../../react-native/React/**", 249 | "$(SRCROOT)/../../react-native/React/**", 250 | "$(SRCROOT)/../../react-native/React/**/**", 251 | "$(SRCROOT)/../../../OpenCV/**", 252 | ); 253 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 254 | LD_RUNPATH_SEARCH_PATHS = "$(inherited)"; 255 | LIBRARY_SEARCH_PATHS = "$(inherited)"; 256 | OTHER_CFLAGS = "$(inherited)"; 257 | OTHER_LDFLAGS = ( 258 | "$(inherited)", 259 | "-ObjC", 260 | "-lc++", 261 | ); 262 | PRODUCT_NAME = RNOpenCV; 263 | SKIP_INSTALL = YES; 264 | STRIP_STYLE = all; 265 | TARGETED_DEVICE_FAMILY = "1,2"; 266 | }; 267 | name = Debug; 268 | }; 269 | 58B511F11A9E6C8500147676 /* Release */ = { 270 | isa = XCBuildConfiguration; 271 | buildSettings = { 272 | ENABLE_ON_DEMAND_RESOURCES = NO; 273 | FRAMEWORK_SEARCH_PATHS = ( 274 | "$(inherited)", 275 | "$(SRCROOT)/../../../ios/Pods", 276 | "$(SRCROOT)/../../../ios", 277 | "$(SRCROOT)/../../../ios/Pods/OpenCV/**", 278 | ); 279 | GCC_NO_COMMON_BLOCKS = YES; 280 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 281 | GCC_PREFIX_HEADER = "$(PROJECT_DIR)/PrefixHeader.pch"; 282 | GCC_VERSION = ""; 283 | HEADER_SEARCH_PATHS = ( 284 | "$(inherited)", 285 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 286 | "$(SRCROOT)/../../../React/**", 287 | "$(SRCROOT)/../../react-native/React/**", 288 | "$(SRCROOT)/../../react-native/React/**", 289 | "$(SRCROOT)/../../react-native/React/**/**", 290 | "$(SRCROOT)/../../../OpenCV/**", 291 | ); 292 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 293 | LD_RUNPATH_SEARCH_PATHS = "$(inherited)"; 294 | LIBRARY_SEARCH_PATHS = "$(inherited)"; 295 | OTHER_CFLAGS = "$(inherited)"; 296 | OTHER_LDFLAGS = ( 297 | "$(inherited)", 298 | "-ObjC", 299 | "-lc++", 300 | ); 301 | PRODUCT_NAME = RNOpenCV; 302 | SKIP_INSTALL = YES; 303 | STRIP_STYLE = all; 304 | TARGETED_DEVICE_FAMILY = "1,2"; 305 | }; 306 | name = Release; 307 | }; 308 | /* End XCBuildConfiguration section */ 309 | 310 | /* Begin XCConfigurationList section */ 311 | 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNOpenCV" */ = { 312 | isa = XCConfigurationList; 313 | buildConfigurations = ( 314 | 58B511ED1A9E6C8500147676 /* Debug */, 315 | 58B511EE1A9E6C8500147676 /* Release */, 316 | ); 317 | defaultConfigurationIsVisible = 0; 318 | defaultConfigurationName = Release; 319 | }; 320 | 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNOpenCV" */ = { 321 | isa = XCConfigurationList; 322 | buildConfigurations = ( 323 | 58B511F01A9E6C8500147676 /* Debug */, 324 | 58B511F11A9E6C8500147676 /* Release */, 325 | ); 326 | defaultConfigurationIsVisible = 0; 327 | defaultConfigurationName = Release; 328 | }; 329 | /* End XCConfigurationList section */ 330 | }; 331 | rootObject = 58B511D31A9E6C8500147676 /* Project object */; 332 | } 333 | -------------------------------------------------------------------------------- /ios/RNOpenCV.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | 3 | 5 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "name": "@pickupp/react-native-opencv", 4 | "version": "1.1.0", 5 | "description": "OpenCV binding for recat-native", 6 | "main": "index.js", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/pickuppdev/react-native-opencv" 13 | }, 14 | "homepage": "https://github.com/pickuppdev/react-native-opencv", 15 | "keywords": [ 16 | "react-native" 17 | ], 18 | "author": "", 19 | "contributors": [ 20 | { 21 | "name": "Allen Ng", 22 | "email": "allen.ng@pickupp.io" 23 | },{ 24 | "name": "Lawrence Ho", 25 | "email": "clong@pickupp.io" 26 | } 27 | ], 28 | "license": "MIT", 29 | "peerDependencies": { 30 | "react-native": "^0.41.2" 31 | }, 32 | "podName": "react-native-opencv" 33 | } 34 | -------------------------------------------------------------------------------- /react-native-opencv.podspec: -------------------------------------------------------------------------------- 1 | require 'json' 2 | 3 | package = JSON.parse(File.read(File.join(__dir__, 'package.json'))) 4 | 5 | Pod::Spec.new do |s| 6 | s.name = package['podName'] 7 | s.version = package['version'] 8 | s.license = package['license'] 9 | s.homepage = package['homepage'] 10 | s.authors = package['contributors'].flat_map { |author| { author['name'] => author['email'] } } 11 | s.summary = package['description'] 12 | s.source = { :git => package['repository']['url'] } 13 | s.source_files = 'ios/*.{h,m,mm}' 14 | s.platform = :ios, '8.0' 15 | s.requires_arc = true 16 | 17 | s.dependency "React" 18 | s.dependency "OpenCV", '~> 3.4.2' 19 | 20 | end 21 | 22 | 23 | --------------------------------------------------------------------------------