原文首发: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 打赏的.
网友评论