-1

Here I'm trying to process image after scanning it, using OpenCV library in iOS. But I am unable you figure out how to pass image source in imread() function.

the input for image that I have to pass is in below line :-

cv::Mat input = cv::imread("tesy1.jpeg", IMREAD_UNCHANGED );

Exactly how to use imread() fuction to pass image?

Can anyone help me out?

//My code + (cv::Mat)cvMatFromUIImage2:(UIImage*)image {

    cv::Mat input = cv::imread("tesy1.jpeg", IMREAD_UNCHANGED );
    int maxdim = input.cols; //std::max(input.rows,input.cols);
    const int dim = 1024;
    if ( maxdim > dim )
    {
        double scale = (double)dim/(double)maxdim;
        cv::Mat t;
        cv::resize( input, t, cv::Size(), scale,scale );
        input = t;
    }
    if ( input.type()!=CV_8UC3 )
       CV_Error(CV_HAL_ERROR_UNKNOWN,"!bgr");
    cv::Mat result;
    input.copyTo( result ); // result is just for drawing the text rectangles

    cv::Mat median;
    cv::medianBlur(input,median,5);
    cv::Mat localmax;
    // find local maximum
    cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT,cv::Size(15,15) );
    cv::morphologyEx( median,localmax,cv::MORPH_CLOSE,kernel,cv::Point(-1,-1),1,cv::BORDER_REFLECT101 );

    std::vector< cv::Rect > bb;
    // detectLetters by @William, modified to internally do the grayscale conversion if necessary
    // https://stackoverflow.com/questions/23506105/extracting-text-opencv?rq=1
//    detectLetters( input, bb );
    // compose a simple Gaussian model for text background (still assumed white)
    cv::Mat mask( input.size(),CV_8UC1,cv::Scalar( 0 ) );
    if ( bb.empty() )
        return input; // TODO; none found
    for ( size_t i=0;i<bb.size(); ++i )
    {
        cv::rectangle( result, bb[i], cv::Scalar(0,0,255),2,8 ); // visualize only
        cv::rectangle( mask, bb[i], cv::Scalar( 1 ), -1 ); // create a mask for cv::meanStdDev
    }
    cv::Mat mean,dev;
    cv::meanStdDev( localmax, mean, dev, mask );
    if ( mean.type()!=CV_64FC1 || dev.type()!=CV_64FC1 || mean.size()!=cv::Size(1,3) || dev.size()!=cv::Size(1,3) )
        CV_Error(CV_HAL_ERROR_UNKNOWN, "should never happen");
    double minimum[3];
    double maximum[3];
    // simply truncate the localmax according to our simple Gaussian model (+/- one standard deviation)
    for ( unsigned int u=0;u<3;++u )
    {
        minimum[u] = mean.at<double>(u ) - dev.at<double>( u );
        maximum[u] = mean.at<double>(u ) + dev.at<double>( u );
    }
    for ( int y=0;y<mask.rows;++y){
        for ( int x=0;x<mask.cols;++x){
            cv::Vec3b & col = localmax.at<cv::Vec3b>(y,x);
            for ( unsigned int u=0;u<3;++u )
            {
                if ( col[u]>maximum[u] )
                    col[u]=maximum[u];
                else if ( col[u]<minimum[u] )
                    col[u]=minimum[u];
            }
        }
    }
    // do the per pixel gain then
    cv::Mat dst;
    input.copyTo( dst );
    for ( int y=0;y<input.rows;++y){
        for ( int x=0;x<input.cols;++x){
            const cv::Vec3b & v1=input.at<cv::Vec3b>(y,x);
            const cv::Vec3b & v2=localmax.at<cv::Vec3b>(y,x);
            cv::Vec3b & v3=dst.at<cv::Vec3b>(y,x);
            for ( int i=0;i<3;++i )
            {
                double gain = 255.0/(double)v2[i];
                v3[i] = cv::saturate_cast<unsigned char>( gain * v1[i] );
            }
        }
    }
    // and dst is the result
    return dst;
}
RB RB
  • 166
  • 18
  • *"This isn't working"* is a poor description of the problem. We can't help you until we know what the problem is. And for Xmas sake, test if the image was loaded successfully before doing anything else: `if (!input.data) { // print error and quit } ` – karlphillip Feb 02 '20 at 11:58
  • @karlphillip No actually image wasn't loaded. because I am not able to figure out how to pass the image in imread() function – RB RB Feb 02 '20 at 12:12
  • I agree with @karlphillip this problem needs more description. Also, what part of this code needs to be run on iOS. You cannot find an image by name like that in the iOS. You have to look for the bundle etc. Maybe if you show us how are you interacting with Swift or Obj-C code we can help you – Güngör Basa Feb 02 '20 at 12:49
  • @GüngörBasa the code is in C++ which is supposed to be used in swift. This code is written in .mm file.I am not able to get how to describe this problem another way. – RB RB Feb 02 '20 at 13:04
  • You can read an image as simple as: `cv::Mat input = cv::imread("tesy1.jpeg");`. The problem seems to be that you're expecting that the application is be able to find *tesy1.jpeg* in the same directory where your binary executable is. However, it seems that when the application runs, it's base directory is some other place. You need to find where that place is and drop the image there. A simple way to do this is to create a small `cv::Mat` and use `cv::imwrite()` to dump that into a file. Then, just search the directories for this new file and you'll know where to put the jpeg. – karlphillip Feb 02 '20 at 15:31
  • @karlphillip thank you for answering my query. this "tesy1,jpeg", I tried directly putting referring demo, because I was not getting the other way to pass the Image path. or to be precise from where I will find image path – RB RB Feb 02 '20 at 15:39
  • Is it now clear? I have edited my query, Thank you guys in advance for your help and suggesstions – RB RB Feb 02 '20 at 16:44
  • You should use `Bundle` or `NSBundle` to get your application path most likely. After you get that, you will be able to read image data. Following link might give you an idea about how you can use `Bundle` https://www.hackingwithswift.com/example-code/system/how-to-find-the-path-to-a-file-in-your-bundle – Güngör Basa Feb 03 '20 at 07:21
  • @GüngörBasa It worked. thanks a lot – RB RB Feb 03 '20 at 08:59

1 Answers1

0

Finally issue is sorted out,I got the solution. Need to first convert image into cv:Mat

Reference :- Scanned Document - Text & Background clarity not good using OpenCV + iOS

Below method will convert UIImage to cvMat

+(cv::Mat)cvMatFromUIImage:(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,
                                                    cols,
                                                    rows,
                                                    8,
                                                    cvMat.step[0],
                                                    colorSpace,
                                                    kCGImageAlphaNoneSkipLast
                                                    | kCGBitmapByteOrderDefault); 

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