Как сделать область черной за пределами cgrect на UIImage?

#ios #objective-c #opencv #core-graphics

#iOS #objective-c #opencv #ядро-графика

Вопрос:

Я использую OpenCV для обнаружения лица на изображении, однако мой вопрос не связан с opencv, я думаю, что он связан только с CoreGraphics. Вот мой код в UIImageView (категория) для определения лица и рисования прямоугольника над ним.

 - (void)detectFeature:(NSString *)feature
{

NSUInteger                scale;

IplImage                * image;
IplImage                * smallImage;
NSString                * xmlPath;
CvHaarClassifierCascade * cascade;
CvMemStorage            * storage;
CvSeq                   * faces;
UIAlertView             * alert;
CGImageRef                imageRef;
CGColorSpaceRef           colorSpaceRef;
CGContextRef              context;
CvRect                    rect;
CGRect                    faceRect;


scale = 2;

cvSetErrMode( CV_ErrModeParent );

xmlPath    = [ [ NSBundle mainBundle ] pathForResource: feature ofType: @"xml" ];
if (xmlPath == nil) {
    NSLog(@"we don't have an xml file for this feature. this feature is can not be detacted");
}
else {
    [self scaleAndRotateImage:self.image];
    image      = [ self createIplImage: self.image ];
    smallImage = cvCreateImage( cvSize( image->width / scale, image->height / scale ), IPL_DEPTH_8U, 3 );

    cvPyrDown( image, smallImage, CV_GAUSSIAN_5x5 );

    cascade = ( CvHaarClassifierCascade * )cvLoad( [ xmlPath cStringUsingEncoding: NSASCIIStringEncoding ], NULL, NULL, NULL );
    storage = cvCreateMemStorage( 0 );
    faces   = cvHaarDetectObjects( smallImage, cascade, storage, ( float )1.2, 2, CV_HAAR_DO_CANNY_PRUNING, cvSize( 20, 20 ) );

    cvReleaseImage( amp;smallImage );

    imageRef      = self.image.CGImage;
    colorSpaceRef = CGColorSpaceCreateDeviceRGB();
    context       = CGBitmapContextCreate
    (
     NULL,
     self.image.size.width,
     self.image.size.height,
     8,
     self.image.size.width * 4,
     colorSpaceRef,
     kCGImageAlphaPremultipliedLast | kCGBitmapByteOrderDefault
     );

    CGContextDrawImage
    (
     context,
     CGRectMake( 0, 0, self.image.size.width, self.image.size.height ),
     imageRef
     );

    CGContextSetLineWidth( context, 1 );
    CGContextSetRGBStrokeColor( context, ( CGFloat )0, ( CGFloat )0, ( CGFloat )0, ( CGFloat )0.5 );
    CGContextSetRGBFillColor( context, ( CGFloat )1, ( CGFloat )1, ( CGFloat )1, ( CGFloat )0.5 );

    if( faces->total == 0 )
    {
        alert = [ [ UIAlertView alloc ] initWithTitle: @"No Feature" message: @"No features were detected in the picture. Please try with another one." delegate: NULL cancelButtonTitle: @"OK" otherButtonTitles: nil ];

        [ alert show ];
    }
    else
    {

        for( int i = 0; i < faces->total; i   )
        {
            rect     = *( CvRect * )cvGetSeqElem( faces, i );
            faceRect = CGContextConvertRectToDeviceSpace( context, CGRectMake( rect.x * scale, rect.y * scale, rect.width * scale, rect.height * scale ) );

            CGContextFillRect( context, faceRect );
            CGContextStrokeRect( context, faceRect );
        }

        self.image = [ UIImage imageWithCGImage: CGBitmapContextCreateImage( context ) ];
    }

    CGContextRelease( context );
    CGColorSpaceRelease( colorSpaceRef );
    cvReleaseMemStorage( amp;storage );
    cvReleaseHaarClassifierCascade( amp;cascade );
    cvReleaseImage( amp;smallImage );
}

}
  

Что делает этот код, так это рисует прямоугольник над моим UIImage. и оставьте остальную часть изображения как есть. Я хотел бы изменить всю область UIImage на черный, кроме обнаруженного прямоугольника.

На данный момент мне удалось обрезать изображение. Но я не хочу этого делать. размер изображения должен быть таким же, я просто хочу затемнить остальную область изображения.

Комментарии:

1. У меня сейчас нет доступного кода, но я знаю, что вы можете выполнять операции с масками с помощью OpenCV, которые должны выполнить то, что вы хотите.

Ответ №1:

Я пошагово разбил свой ответ.Надеюсь, это поможет.

После обнаружения всех граней нарисуйте заполненную прямоугольную область вместо пути в качестве нового изображения. После этого нарисуйте черное изображение исходного размера.

Затем создайте новый контекст, нарисуйте черное изображение, затем нарисуйте изображение пути (изображение с прямым путем) с помощью kCGBlendModeDestinationOut в режиме наложения.Сохраните результат как result1.

Снова создайте новый контекст, нарисуйте исходное изображение, затем нарисуйте изображение пути (изображение с прямым путем) с помощью KCGBLENDMODEDESTINATION в режиме наложения.Сохраните результат как result2.

Возьмите новый контекст и нарисуйте оба изображения result1 и result2 kCGBlendModeNormal . Надеюсь, это поможет. Удачного кодирования .. !!

Комментарии:

1. Я понимаю вашу точку зрения. просто возникли трудности с переводом в реальный код.

2. Если вы предоставите мне образец изображения, то есть оригинал, и изображение с полученным вами путем. Я могу предоставить пример кода.

3. В моем коде я уже использую Rect для рисования в контексте, подобном этому — CGContextFillRect (контекст, faceRect ). я не использую какой-либо путь сортировки.

4. «Что делает этот код, он рисует прямоугольник над моим UIImage» я спрашиваю это изображение.