2017-05-01 4 views
13

adaptive Schwelle anzuwenden Ich versuche, adaptive Schwellwertbildung zu einem Bild eines A4-Papier anwenden, wie unten gezeigt:OpenCV - Wie ein Bild auf iOS

ich den Code verwenden, unter die anzuwenden Bildmanipulation:

+ (UIImage *)processImageWithOpenCV:(UIImage*)inputImage { 
    cv::Mat cvImage = [inputImage CVMat]; 
    cv::Mat res; 
    cv::cvtColor(cvImage, cvImage, CV_RGB2GRAY); 
    cvImage.convertTo(cvImage,CV_32FC1,1.0/255.0); 
    CalcBlockMeanVariance(cvImage,res); 
    res=1.0-res; 
    res=cvImage+res; 
    cv::threshold(res,res, 0.85, 1, cv::THRESH_BINARY); 
    cv::resize(res, res, cv::Size(res.cols/2,res.rows/2)); 
    return [UIImage imageWithCVMat:cvImage]; 
} 

void CalcBlockMeanVariance(cv::Mat Img,cv::Mat Res,float blockSide=13) // blockSide - the parameter (set greater for larger font on image) 
{ 
cv::Mat I; 
Img.convertTo(I,CV_32FC1); 
Res=cv::Mat::zeros(Img.rows/blockSide,Img.cols/blockSide,CV_32FC1); 
cv::Mat inpaintmask; 
cv::Mat patch; 
cv::Mat smallImg; 
cv::Scalar m,s; 

for(int i=0;i<Img.rows-blockSide;i+=blockSide) 
{ 
    for (int j=0;j<Img.cols-blockSide;j+=blockSide) 
    { 
     patch=I(cv::Rect(j,i,blockSide,blockSide)); 
     cv::meanStdDev(patch,m,s); 
     if(s[0]>0.01) // Thresholding parameter (set smaller for lower contrast image) 
     { 
      Res.at<float>(i/blockSide,j/blockSide)=m[0]; 
     }else 
     { 
      Res.at<float>(i/blockSide,j/blockSide)=0; 
     } 
    } 
} 

cv::resize(I,smallImg,Res.size()); 

cv::threshold(Res,inpaintmask,0.02,1.0,cv::THRESH_BINARY); 

cv::Mat inpainted; 
smallImg.convertTo(smallImg,CV_8UC1,255); 

inpaintmask.convertTo(inpaintmask,CV_8UC1); 
inpaint(smallImg, inpaintmask, inpainted, 5, cv::INPAINT_TELEA); 

cv::resize(inpainted,Res,Img.size()); 
Res.convertTo(Res,CV_8UC3); 

} 

Obwohl die eingegebenen Bildgraustufen wird, gibt sie ein gelbliches Bild wie unten gezeigt:

Meine Hypothese ist, dass während der Konvertierung zwischen cv :: Mat und UIImage etwas passiert ist, was zum Farbbild geführt hat, aber ich kann nicht herausfinden, wie ich dieses Problem beheben kann.

** Bitte ignorieren Sie die Statusleiste, da diese Bilder Screenshots der iOS App sind.

Update: Ich habe versucht, mit CV_8UC1 statt CV_8UC3 für Res.convertTo() und hinzugefügt cvtColor(Res, Res, CV_GRAY2BGR); aber bin immer noch sehr ähnliche Ergebnisse.

Könnte es die Konvertierung zwischen cv :: mat und UIImage sein, die dieses Problem verursacht?

Ich möchte mein Bild wie folgt aussehen.

+0

Sie initialisiert haben 'Res' als' CV_32FC1', und dann konvertieren Sie es zu 'uchar' mit' Res.convertTo (Res, CV_8UC3); ', das scheint fischig zu sein, versuchen Sie es mit 'Res.convertTo (Res, CV_8UC1);' und später verwenden Sie 'cvtColor' – ZdaR

+0

@ZdaR Können Sie bitte erläutern, was Sie mit' cvtColor' meinen? Ich habe 'CV_8UC1' gefolgt von 'cvtColor (Res, Res, CV_GRAY2BGR);' versucht. Ich bekomme jedoch immer noch sehr ähnliche Ergebnisse. Irgendwelche anderen Vorschläge? –

Antwort

5

Sie OpenCV Framework verwenden können und unter Code implementieren

+(UIImage *)blackandWhite:(UIImage *)processedImage 
    { 
     cv::Mat original = [MMOpenCVHelper cvMatGrayFromAdjustedUIImage:processedImage]; 

     cv::Mat new_image = cv::Mat::zeros(original.size(), original.type()); 

     original.convertTo(new_image, -1, 1.4, -50); 
     original.release(); 

     UIImage *blackWhiteImage=[MMOpenCVHelper UIImageFromCVMat:new_image]; 
     new_image.release(); 

     return blackWhiteImage; 
    } 

+ (cv::Mat)cvMatGrayFromAdjustedUIImage:(UIImage *)image 
{ 
    cv::Mat cvMat = [self cvMatFromAdjustedUIImage:image]; 
    cv::Mat grayMat; 
    if (cvMat.channels() == 1) { 
     grayMat = cvMat; 
    } 
    else { 
     grayMat = cv :: Mat(cvMat.rows,cvMat.cols, CV_8UC1); 
     cv::cvtColor(cvMat, grayMat, cv::COLOR_BGR2GRAY); 
    } 
    return grayMat; 
} 

+ (cv::Mat)cvMatFromAdjustedUIImage:(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 

    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); 

    CGContextDrawImage(contextRef, CGRectMake(0, 0, cols, rows), image.CGImage); 
    CGContextRelease(contextRef); 
    return cvMat; 
} 


+ (UIImage *)UIImageFromCVMat:(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 

    UIImage *image = [[UIImage alloc] initWithCGImage:imageRef]; 
    CGImageRelease(imageRef); 
    CGDataProviderRelease(provider); 
    CGColorSpaceRelease(colorSpace); 

    return image; 
} 

seine Arbeit für mich die Ausgabe für das Dokument überprüfen

+0

Hey danke, Kannst du ein Beispiel geben? –

+0

ich habe volle Arbeitscode .., übergeben Sie einfach Ihr Bild zu verarbeiteten Bild in + (UIImage *) blackandWhite: (UIImage *) verarbeiteteBild Methode –

+0

Wie in, ein Beispiel für ein Ergebnis aus diesem Code –

3

Versuchen Sie folgendes:

+ (UIImage *)processImageWithOpenCV:(UIImage*)inputImage { 
    cv::Mat cvImage = [inputImage CVMat]; 
    threshold(cvImage, cvImage, 128, 255, cv::THRESH_BINARY); 
    return [UIImage imageWithCVMat:cvImage]; 
} 

Ergebnis Bild:

+0

Obwohl dies eine Art von Thresholding ist und es funktioniert, würde ich gerne adaptives Thresholding implementieren, da es zu besseren Ergebnissen führt - die Besonderheiten des adaptiven Thresholding können hier gefunden werden; http://hanzratech.in/2015/01/21/adaptive-thresholding.html –

Verwandte Themen