美文网首页iOS Developer环境集成牛叉的demo
OC调用C++函数和openCV库6坑总结

OC调用C++函数和openCV库6坑总结

作者: wg689 | 来源:发表于2016-06-05 11:11 被阅读1101次

    原文首发:http://www.jianshu.com/p/ae1896a50b0e

    项目背景

    公司的app 产品涉及中医诊断,中医诊断是使用中医的望闻问切对病情进行诊断,我们公司的app 需要将这个功能整合到app 里面,中医诊断这个项目是上海某医科大学和上海某985大学以及我们公司一起合作的一个项目,我作为iOS 码农负责三方的技术对接,我需要调用他们两家公司提供的C++库  ,C++源码里面需要用openCV,xcode 的开发环境调用C++ 的库总体来说不难,在这个过程中也遇到了一些C++ 和 openCv 和OC 语言的差异问题,需要解决.主要是6个方面的问题

    1) 使用openCv 库的时候需要对xcode 进行配置,配置见这篇文章open Cv配置,关于openCV 如何配置巧哥也写了文章,蛮实用  ,openCV 配置是去年配置的,具体在这里就不介绍了,其实中途也是需要细加耐心的.这里不介绍了.

    2)修改库的C++库的 .cpp文件为.mm 文件,这个集成百度地图的时候也要这么整,so easy. 就不多说了,这个修改了 ,xcode 由开始的一片红 变成可以编译通过.

    3)C++ 里面图像处理的函数tcmPro进行图像处理的时候接收是接收的IplImage* 类型的图片,而我们从相机获得的图片是UIImage类型的图片,需要将UIImage的图片转换成IPIImage* 类型的图片

    int tcmPro(IplImage* input,int type)

    如下是图片类型转换的函数,github上有UIImage (UIImage_OpenCV) 这个分类,这个分类里面有 +(IplImage*)convertToIplImage:(UIImage*)image这个函数.

    +(IplImage*)convertToIplImage:(UIImage*)image

    {

    CGImageRef imageRef = image.CGImage;

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

    IplImage *iplImage = cvCreateImage(cvSize(image.size.width, image.size.height), IPL_DEPTH_8U, 4);

    CGContextRef contextRef = CGBitmapContextCreate(iplImage->imageData, iplImage->width, iplImage->height, iplImage->depth, iplImage->widthStep, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrderDefault);

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

    CGContextRelease(contextRef);

    CGColorSpaceRelease(colorSpace);

    IplImage *ret = cvCreateImage(cvGetSize(iplImage), IPL_DEPTH_8U, 3);

    cvCvtColor(iplImage, ret, CV_RGB2BGR);

    cvReleaseImage(&iplImage);

    return ret;

    }

    4)进行图像处理的时候,涉及到算法 ,算法模板文件加载在.xml 文件中,人家搞C++ 的时候,直接用C++ 代码的方法加载的xml文件,我们用别人的库 ,在xcode 里面使用C++方法加载xml 文件,肯定加载不到xml 文件的.

    C++ 加载xml 的方法 直接使用openCV 里面的函数  cvLoad 就可以加载,调试的时候这个方法到xcode 中 cascade 变为空

        char* cascade_name = "haarcascade_frontalface_alt2.xml";

       char* cascade_name = "../assets/haarcascade_frontalface_alt2.xml";

       (xcode 里面为null 的) cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );

    Xcode 使用C++ 的方法无法加载xml 改用OC 的方法加载xml,加载的xml 路径给openCv需要对path 进行NSASCIIStringEncoding,否则还是加载不成功的.

    NSString *path = [[NSBundle mainBundle] pathForResource:@"haarcascade_frontalface_alt2" ofType:@"xml"];

    cascade = (CvHaarClassifierCascade*)cvLoad([path cStringUsingEncoding:NSASCIIStringEncoding], 0, 0, 0 );

    5)上面的几个坑填好了 ,xml 加载完成了,加载后的cascade 有值了 .可是还是和预期效果不一致啊,肿么办?  想了一段时间,我下载的opencV 是最新的,C++人员用的openCv 和我们的版本是不是一致的呢? 带着这个问题屁颠屁颠的给别人打电话,询问他们openCV的版本号,他们是2.4.9  ,我再看看我自己用的版本号,发现版本号不一致,立马重新下载2.4.9 的opencv2.framework  重新试了下 ,还是没有达到预期效果,有调用的C++ 函数有返回值了,可是返回值不对.

    6)返回值不对,查看了下int tcmPro(IplImage* input,int type) 他们的这个函数直接返回一个int 型的数组的指针,C++ 开发人员的话说一次返回多个值的指针,可是OC 除了swift 以外是不能同时接收多个值的返回参数的.

    具体怎么解决这个问题,只有修改c++ 的底层函数了 修改后的函数是这样的核心代码,本来是需要返回returnResult[0],returnResult[1],returnResult[2],returnResult[3]这四个值的,现在将这四个值组合成一个四位数的result2 ,到OC 里面再解析出returnResult[0],returnResult[1],returnResult[2],returnResult[3]各为多少.

    下面是将returnResult[0],returnResult[1],returnResult[2],returnResult[3] 变换为result2的过程

    result2 = returnResult[0]*1000 + returnResult[1]*100 +returnResult[2]*10 +returnResult[3];

    printf("shetou---- %d%d%d%d ",returnResult[0],returnResult[1],returnResult[2],returnResult[3]);

    至此所有的问题都解决了 ,这个不能写个demo 的,相关的源码是公司的机密的哈 ,抱歉,各位看官!

    如果喜欢就给个赞哈!! 不需要RMB 打赏的.

    相关文章

      网友评论

        本文标题:OC调用C++函数和openCV库6坑总结

        本文链接:https://www.haomeiwen.com/subject/heqrdttx.html