OpenCV - 如何在 iOS 上将自适应阈值应用于图像

2024-04-13

我正在尝试将自适应阈值应用于 A4 纸的图像,如下所示:

我使用下面的代码来应用图像处理:

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

}

Although the inputted image is greyscaled, it outputs an yellowish image as shown below:

我的假设是,在 cv::Mat 和 UIImage 之间进行转换时,发生了一些导致彩色图像的事情,但是我不知道如何解决这个问题。

**请忽略状态栏,因为这些图像是 iOS 应用程序的屏幕截图。

更新: 我尝试过使用CV_8UC1代替CV_8UC3 for Res.convertTo()并添加了cvtColor(Res, Res, CV_GRAY2BGR);但我仍然得到非常相似的结果。

难道是 cv::mat 和 UIImage 之间的转换导致了这个问题?

我希望我的图像如下所示。


您可以使用OpenCV框架并实现以下代码

 +(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;
}

its working for me check the output for your document

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OpenCV - 如何在 iOS 上将自适应阈值应用于图像 的相关文章

随机推荐

  • 在delphi中禁用窗体大小调整

    有什么方法可以阻止用户调整表单大小吗 目前我正在使用 当表单大小改变时 MainForm Height 761 MainForm Width 777 但这看起来很可怕 因为当用户尝试更改表单大小时它会闪烁 固定尺寸很简单 你有两个选择 De
  • Cassandra Nodetool URISyntaxException:“索引 7 处的 IPv6 地址格式错误”

    Cassandra nodetool 更新 OpenJDK 后抛出错误 nodetool status nodetool Failed to connect to 127 0 0 1 7199 URISyntaxException Malf
  • 什么是托管代码和非托管代码? [复制]

    这个问题在这里已经有答案了 我发现有人说托管代码和非托管代码 有什么不同 它仅适用于 Net吗 你可以阅读这篇维基百科文章 托管代码 http en wikipedia org wiki Managed code 基本上托管代码是一个微软术
  • Box2D - b2body GetUserData 始终返回 null

    我正在尝试根据 box2d 中的 b2body 调整精灵的位置和旋转 创建主体后 我将 userData 属性设置为保存精灵和位置等的主体对象的属性 问题是在勾选方法 b gt GetUserData 中永远不会检索我放入其中的对象 你能看
  • GPS 对比加速度计计算距离

    我正在尝试实现一个健身应用程序 可以在Android 中跟踪跑步速度和跑步距离 看起来我可以使用 GPS 或加速度计来计算这些信息 由于跑步者可能会将手机放在手里 放在肩膀上或放在口袋里 所以我的第一直觉是使用 GPS 获取位置并计算跑步速
  • 如何将 SSH 密钥与 Jenkins 工作流插件结合使用

    有一个由以下执行的常规脚本Jenkins 工作流插件 https github com jenkinsci workflow plugin As 有记录的 https github com jenkinsci workflow plugin
  • 如何让 SWIG 在 C# 中处理 utf8 字符串?

    我正在编写一个可移植的 C 库 它与其他语言 java C python 绑定 我在以下人员的帮助下进行这些绑定SWIG http www swig org 我有一个用 C 编写的类 class MyClass public const c
  • 我可以对字段和构造函数参数使用相同的名称吗?

    class C T a public C T a a a 合法吗 是的 它是合法的并且适用于所有平台 它将正确地将您的成员变量 a 初始化为传入的值 a 一些更干净的人认为以不同的方式命名它们 但并非全部 我个人实际上经常使用它 具有相同变
  • 如何获取 NSString 的宽度?

    我正在尝试获取 NSString 的宽度 例如 NSString myString hello 有没有办法做到这一点 Thanks 这是一个相对简单的方法 只需创建一个具有适当字体的 NSAttributedString 并询问其大小 CG
  • Android 自定义组件中的布局未膨胀

    我在自定义视图中遇到空指针异常 源自LinearLayout 因为它找不到它的子视图 这是代码 public class MyView extends LinearLayout public MyView Context context A
  • DrawingContext.DrawLine:笔没有完全不透明度?

    当我画这样的东西时 这里只是随机画 public partial class MainWindow Window public MainWindow InitializeComponent DrawingVisual visual new
  • 专业密钥的许可证检查

    因此 我想制作一个加载了完整功能的免费应用程序 在应用程序检测到许可的专业版密钥之前 专业版功能将被禁用 当然 我想让专业密钥使用 LVL 检查其许可证 虽然到目前为止我知道如何正确做事 但我不知道如何使专业版密钥与应用程序进行通信以启用专
  • 当在封闭类模板中引用特化时,成员类模板的隐式实例化

    include
  • fetch-api 中的“最大重定向”错误意味着什么?

    我试图从网站获取一些数据 但收到以下错误 FetchError maximum redirect reached at
  • 在 Bash 中的函数内部使用声明

    我想使用函数更改全局变量 或至少附加到它 input Hello example input func declare x example input World func echo input 其输出将是 Hello 的原始值 如果该函数
  • 重新排序时无法将 UITableViewCell 从当前位置拖动

    我试图让我的核心数据支持的 UITableView 具有重新排序的能力 在实现所有这些委托和提到的核心数据的一些技术之后here https stackoverflow com q 1077568 147564我发现奇怪的行为 点击编辑按钮
  • 垃圾收集和 JNI 调用

    我遇到 JNI 程序随机内存不足的问题 这是一个 32 位 java 程序 它读取文件 进行一些图像处理 通常使用 250MB 到 1GB 然后 所有这些对象都会被丢弃 然后程序对 JNI 程序进行一系列调用 通常需要 100 250MB
  • 转换为Weka日期格式

    我有一个带有一些属性的 csv 文件 一种是日期属性 日期采用这种形式 yyyy mm dd hh mm ss 但 Weka 将其视为名义类型而不是日期类型 如何解决这个问题 请在这件事上给予我帮助 我用Weka资源管理器 一个很好的参考
  • 执行 `brew tap exolnet/homebrew-deprecated` 时出错

    我要安装 电子邮件受保护 cdn cgi l email protection在我的 MacBook Pro 和 Macos M1 上 我想执行以下步骤 brew tap exolnet homebrew deprecated brew i
  • OpenCV - 如何在 iOS 上将自适应阈值应用于图像

    我正在尝试将自适应阈值应用于 A4 纸的图像 如下所示 我使用下面的代码来应用图像处理 UIImage processImageWithOpenCV UIImage inputImage cv Mat cvImage inputImage