OpenCV QRCodeDetector not working for IOS objective C++

Viewed 155

I am trying to complete an app for a university project that will allow the user to take a photo which contains a QR code and some specific colours that could change over time. My app should be able to detect the QR code and changes in the colours. I am trying to use react native and openCV to complete this task concentrating on IOS first (I had hoped it would be easier). So far, using the openCV tutorial by brainhubeu/react-native-opencv-tutorial on GitHub, I am to take a picture, check for blur, but when it comes to detecting and decoding the QR code, its doesn't seem to be locating any QR in the image.

#import "RNOpenCVLibrary.h"
#import <React/RCTLog.h>

@implementation RNOpenCVLibrary

- (dispatch_queue_t)methodQueue
{
  return dispatch_get_main_queue();
}

RCT_EXPORT_MODULE()

RCT_EXPORT_METHOD(addEvent:(NSString *)name location:(NSString *)location)
{
  RCTLogInfo(@"Pretending to create an event %@ at %@", name, location);
};

RCT_EXPORT_METHOD(checkForBlurryImage:(NSString *)imageAsBase64 callback:(RCTResponseSenderBlock)callback) {
  RCTLog(@"%@", imageAsBase64);
  UIImage* image = [self decodeBase64ToImage:imageAsBase64];
  BOOL isImageBlurryResult = [self isImageBlurry:image];

  id objects[] = { isImageBlurryResult ? @YES : @NO };
  NSUInteger count = sizeof(objects) / sizeof(id);
  NSArray *dataArray = [NSArray arrayWithObjects:objects
                                           count:count];
  
  callback(@[[NSNull null], dataArray]);
};

RCT_EXPORT_METHOD(checkForQRCode:(NSString *)imageAsBase64) {
  RCTLog(@"%@", imageAsBase64);
  UIImage* image = [self decodeBase64ToImage:imageAsBase64];
  
  cv::QRCodeDetector qrDecoder = cv::QRCodeDetector();
  
  BOOL isQRPresentResult = [self isQRPresent:image];
  
  NSString *decodedQrData = [self decodeQRCode:image];
  //BOOL isQRPresentResult = 1;
    
  //std::string data =  qrDecoder.detectAndDecode(matImage);
  //std::string data = "testing";
  
  //NSString* result = [NSString stringWithUTF8String:data.c_str()];
  //NSString* result = @"test";
  RCTLogInfo(@"Pretending to create an event %@", decodedQrData);
  RCTLog(isQRPresentResult ? @"yes" : @"No");
};

-(BOOL)isQRPresent:(UIImage*)image{
  
  cv::Mat matImage = [self convertUIImageToCVMat:image];
  cv::Mat matImageGrey;
  // converting image's color space (RGB) to grayscale
  cv::cvtColor(matImage, matImageGrey, cv::COLOR_BGRA2GRAY);
  std::vector<cv::Point> points;
  
  cv::QRCodeDetector qrDecoder = cv::QRCodeDetector();
  return qrDecoder.detect(matImageGrey, points);
  
};

-(NSString*)decodeQRCode:(UIImage*)image{
  
  cv::Mat matImage = [self convertUIImageToCVMat:image];
  cv::Mat matImageGrey;
  // converting image's color space (RGB) to grayscale
  cv::cvtColor(matImage, matImageGrey, cv::COLOR_BGRA2GRAY);
  
  cv::QRCodeDetector qrDecoder = cv::QRCodeDetector();
  std::string qrData;
  qrData = qrDecoder.detectAndDecode(matImageGrey);
  return [NSString stringWithUTF8String:qrData.c_str()];
  
};

- (cv::Mat)convertUIImageToCVMat:(UIImage *)image {
  CGColorSpaceRef colorSpace = CGImageGetColorSpace(image.CGImage);
  CGFloat cols = image.size.width;
  CGFloat rows = image.size.height;
  
  cv::Mat cvMat(rows, cols, CV_8UC4); // 8 bits per component, 4 channels (color channels + alpha)
  
  CGContextRef contextRef = CGBitmapContextCreate(cvMat.data,                 // Pointer to  data
                                                  cols,                       // Width of bitmap
                                                  rows,                       // Height of bitmap
                                                  8,                          // Bits per component
                                                  cvMat.step[0],              // Bytes per row
                                                  colorSpace,                 // Colorspace
                                                  kCGImageAlphaNoneSkipLast |
                                                  kCGBitmapByteOrderDefault); // Bitmap info flags
  
  CGContextDrawImage(contextRef, CGRectMake(0, 0, cols, rows), image.CGImage);
  CGContextRelease(contextRef);
  
  return cvMat;
};

- (UIImage *)decodeBase64ToImage:(NSString *)strEncodeData {
  NSData *data = [[NSData alloc]initWithBase64EncodedString:strEncodeData options:NSDataBase64DecodingIgnoreUnknownCharacters];
  return [UIImage imageWithData:data];
};

- (BOOL) isImageBlurry:(UIImage *) image {
  // converting UIImage to OpenCV format - Mat
  cv::Mat matImage = [self convertUIImageToCVMat:image];
  cv::Mat matImageGrey;
  // converting image's color space (RGB) to grayscale
  cv::cvtColor(matImage, matImageGrey, cv::COLOR_BGRA2GRAY);
  
  cv::Mat dst2 = [self convertUIImageToCVMat:image];
  cv::Mat laplacianImage;
  dst2.convertTo(laplacianImage, CV_8UC1);
  
  // applying Laplacian operator to the image
  cv::Laplacian(matImageGrey, laplacianImage, CV_8U);
  cv::Mat laplacianImage8bit;
  laplacianImage.convertTo(laplacianImage8bit, CV_8UC1);
  
  unsigned char *pixels = laplacianImage8bit.data;
  
  // 16777216 = 256*256*256
  int maxLap = -16777216;
  for (int i = 0; i < ( laplacianImage8bit.elemSize()*laplacianImage8bit.total()); i++) {
    if (pixels[i] > maxLap) {
      maxLap = pixels[i];
    }
  }
  // one of the main parameters here: threshold sets the sensitivity for the blur check
  // smaller number = less sensitive; default = 180
  int threshold = 180;
  
  return (maxLap <= threshold);
};

@end

0 Answers
Related