orientacja detektora twarzy iOS i ustawienie orientacji CIImage

EDYTOWAĆ Znalazłem ten kod, który pomógł z obrazami z przedniej kameryhttp://blog.logichigh.com/2008/06/05/uiimage-fix/

Mam nadzieję, że inni mieli podobny problem i mogą mi pomóc. Nie znalazłem jeszcze rozwiązania. (Może się to wydawać trochę długie, ale tylko kilka kodów pomocniczych)

Używam detektora twarzy ios na zdjęciach pozyskanych z kamery (z przodu iz tyłu), a także obrazów z galerii (używamUIImagePicker - zarówno dla przechwytywania obrazu przez kamerę, jak i wyboru obrazu z galerii - nieużywanie avfoundation do robienia zdjęć jak w demo squarecam)

Dostaję naprawdę pomieszane współrzędne wykrywania (jeśli takie istnieją), więc napisałem krótką metodę debugowania, aby uzyskać granice twarzy, a także narzędzie, które rysuje nad nimi kwadrat, i chciałem sprawdzić, która orientacja detektora pracował:

#define RECTBOX(R)   [NSValue valueWithCGRect:R]
- (NSArray *)detectFaces:(UIImage *)inputimage
{
    _detector = \[CIDetector detectorOfType:CIDetectorTypeFace context:nil options:\[NSDictionary dictionaryWithObject:CIDetectorAccuracyLow forKey:CIDetectorAccuracy\]\];
    NSNumber *orientation = \[NSNumber numberWithInt:\[inputimage imageOrientation\]\]; // i also saw code where they add +1 to the orientation
    NSDictionary *imageOptions = \[NSDictionary dictionaryWithObject:orientation forKey:CIDetectorImageOrientation\];

    CIImage* ciimage = \[CIImage imageWithCGImage:inputimage.CGImage options:imageOptions\];


    // try like this first
    //    NSArray* features = \[self.detector featuresInImage:ciimage options:imageOptions\];
    // if not working go on to this (trying all orientations)
    NSArray* features;

    int exif;
    // ios face detector. trying all of the orientations
    for (exif = 1; exif <= 8 ; exif++)
    {
        NSNumber *orientation = \[NSNumber numberWithInt:exif\];

        NSDictionary *imageOptions = \[NSDictionary dictionaryWithObject:orientation forKey:CIDetectorImageOrientation\];

        NSTimeInterval start = \[NSDate timeIntervalSinceReferenceDate\];

        features = \[self.detector featuresInImage:ciimage options:imageOptions\];

        if (features.count > 0)
        {
            NSString *str = \[NSString stringWithFormat:@"found faces using exif %d",exif\];
                    \[faceDetection log:str\];
            break;
        }
        NSTimeInterval duration = \[NSDate timeIntervalSinceReferenceDate\] - start;
        NSLog(@"faceDetection: facedetection total runtime is %f s",duration);
    }
    if (features.count > 0)
    {
        [faceDetection log:@"-I- Found faces with ios face detector"];
        for(CIFaceFeature *feature in features)
        {
            CGRect rect = feature.bounds;
            CGRect r = CGRectMake(rect.origin.x,inputimage.size.height - rect.origin.y - rect.size.height,rect.size.width,rect.size.height);
            [returnArray addObject:RECTBOX(r)];
        }
        return returnArray;
    } else {
        // no faces from iOS face detector. try OpenCV detector
    }

[1]

Po wypróbowaniu ton różnych zdjęć zauważyłem, że orientacja detektora twarzy nie jest zgodna z właściwością obrazu z kamery. Zrobiłem kilka zdjęć z kamery skierowanej do przodu, gdzie orientacja uiimage wynosiła 3 (zapytanie o imageOrienation), ale detektor twarzy nie znajdował twarzy dla tego ustawienia. Po przejściu przez wszystkie możliwości exif, detektor twarzy w końcu zbierał twarze, ale dla innej orientacji razem.

! [1]:http://i.stack.imgur.com/D7bkZ.jpg

Jak mogę to rozwiązać? Czy w moim kodzie jest błąd?

Kolejny problem, który miałem, (ale ściśle związany z wykrywaczem twarzy), gdy wykrywacz twarzy wychwytuje twarze, ale dla „złej” orientacji (dzieje się to głównie na przednim aparacie)UIImage początkowo używany wyświetla się poprawnie w widoku uiiimageview, ale kiedy rysuję kwadratową nakładkę (używam opencv w mojej aplikacji, więc zdecydowałem się przekonwertowaćUIImage cvmat, aby narysować nakładkę z opencv) cały obraz jest obrócony o 90 stopni (tylko obraz cvmat, a nieUIImage początkowo wyświetlany)

Rozumiem, że rozumiem tutaj, że wykrywacz twarzy miesza się z jakimś buforem (kontekstem?), Którego używa konwersja UIimage na matę opencv. Jak mogę oddzielić te bufory?

Kod do konwersji uiimage na cvmat to (ze „słynnego”UIImage ktoś zrobił kategorię):

-(cv::Mat)CVMat
{

    CGColorSpaceRef colorSpace = CGImageGetColorSpace(self.CGImage);
    CGFloat cols = self.size.width;
    CGFloat rows = self.size.height;

    cv::Mat cvMat(rows, cols, CV_8UC4); // 8 bits per component, 4 channels

    CGContextRef contextRef = CGBitmapContextCreate(cvMat.data, // Pointer to backing 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), self.CGImage);
    CGContextRelease(contextRef);

    return cvMat;
}

- (id)initWithCVMat:(const cv::Mat&)cvMat
{
    NSData *data = [NSData dataWithBytes:cvMat.data length:cvMat.elemSize() * cvMat.total()];

    CGColorSpaceRef colorSpace;

    if (cvMat.elemSize() == 1)
    {
        colorSpace = CGColorSpaceCreateDeviceGray();
    }
    else
    {
        colorSpace = CGColorSpaceCreateDeviceRGB();
    }

    CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);

    CGImageRef imageRef = CGImageCreate(cvMat.cols,                                     // Width
                                            cvMat.rows,                                     // Height
                                            8,                                              // Bits per component
                                            8 * cvMat.elemSize(),                           // Bits per pixel
                                            cvMat.step[0],                                  // Bytes per row
                                            colorSpace,                                     // Colorspace
                                            kCGImageAlphaNone | kCGBitmapByteOrderDefault,  // Bitmap info flags
                                            provider,                                       // CGDataProviderRef
                                            NULL,                                           // Decode
                                            false,                                          // Should interpolate
                                            kCGRenderingIntentDefault);                     // Intent   

     self = [self initWithCGImage:imageRef];
     CGImageRelease(imageRef);
     CGDataProviderRelease(provider);
     CGColorSpaceRelease(colorSpace);

     return self;
 }  

 -(cv::Mat)CVRgbMat
 {
     cv::Mat tmpimage = self.CVMat;
     cv::Mat image;
     cvtColor(tmpimage, image, cv::COLOR_BGRA2BGR);
     return image;
 }

 - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)img editingInfo:(NSDictionary *)editInfo {
    self.prevImage = img;
 //   self.previewView.image = img;
    NSArray *arr = [[faceDetection sharedFaceDetector] detectFaces:img];
    for (id r in arr)
    {
         CGRect rect = RECTUNBOX(r);
         //self.previewView.image = img;
         self.previewView.image = [utils drawSquareOnImage:img square:rect];
    }
    [self.imgPicker dismissModalViewControllerAnimated:YES];
    return;
}

questionAnswers(2)

yourAnswerToTheQuestion