看网上方法很多,但版本都不够新,我看了网上一些知识,总结了下,来个最新版Xcode6.1的.

最近主要想做iOS端的车牌识别,所以开始了解OpenCV。有兴趣的可以跟我交流下哈。

一.Opencv的使用:

  步骤:

  1.从官网下载iOS版本的Opencv2.framework。

  2.拖进工程,选择copy items if needed

  3.进入building settings,设置Framework SearchPath:

     设置成$(PROJECT_DIR)/Newtest,这个Newtest是你的项目名,主要是为了定位到你存放的Opencv2.framework所在位置。

  4.使用Opencv的方式:第(1)种全局pch:(不推荐)新建pch文件,修改成:

              #ifdef __cplusplus

              #import <opencv2/opencv.hpp>

              #endif

                并在building setting里的 Incease Sharing of Precompiled Headers项目处:

               设置成$(PROJECT_DIR)/Newtest,同理,这个Newtest是你的项目名,主要是为了定位到你存放的PCH文件所在位置。

              PCH文件以前建工程默认生成,是全局性质的import。Xcode6不再自动生成。苹果引导开发者在某个类要用时才用。

             第(2)种:在需要的地方#import <opencv2/opencv.hpp>

                这里的重点是:使用opencv的类名一定要改成.mm!!

                        比如你专门写了各一个处理图片的类,Imageprocess。可以在.h里加入。

二:灰度化和二值化的主要实现过程:

  其实过程就是这样:

  UIImage(iOS图像类)-> cv::Mat(OpenCV图像类) -> Opencv灰度或二值处理函数 -> UIImage

三:Opencv类Imageprocess代码参考:

Imageprocess.h

  1. //
  2. // Imageprocess.h
  3. // Chepaishibie
  4. //
  5. // Created by shen on 15/1/28.
  6. // Copyright (c) 2015年 shen. All rights reserved.
  7. //
  8.  
  9. #import <Foundation/Foundation.h>
  10. #import <opencv2/opencv.hpp>
  11. #import <UIKit/UIKit.h>
  12.  
  13. @interface Imageprocess : UIViewController
  14.  
  15. - (cv::Mat)cvMatFromUIImage:(UIImage *)image;
  16.  
  17. - (UIImage *)UIImageFromCVMat:(cv::Mat)cvMat;
  18.  
  19. - (IplImage *)CreateIplImageFromUIImage:(UIImage *)image;
  20.  
  21. - (UIImage *)UIImageFromIplImage:(IplImage *)image;
  22.  
  23. - (UIImage *)Grayimage:(UIImage *)srcimage;
  24.  
  25. - (UIImage *)Erzhiimage:(UIImage *)srcimage;
  26.  
  27. int Otsu(unsigned char* pGrayImg , int iWidth , int iHeight);
  28.  
  29. @end

Imageprocess.mm 里面包含了很多函数:

主要是 UIImage->cv::Mat ,cv::Mat->UIImage,UIImage->IplImage,IplImage->UIImage, 灰度化,二值化等,还有个OSTU计算阈值的方法。

  1. //
  2. // Imageprocess.mm
  3. // Chepaishibie
  4. //
  5. // Created by shen on 15/1/28.
  6. // Copyright (c) 2015年 shen. All rights reserved.
  7. //
  8.  
  9. #import "Imageprocess.h"
  10.  
  11. @implementation Imageprocess
  12.  
  13. #pragma mark - opencv method
  14. // UIImage to cvMat
  15. - (cv::Mat)cvMatFromUIImage:(UIImage *)image
  16. {
  17. CGColorSpaceRef colorSpace = CGImageGetColorSpace(image.CGImage);
  18. CGFloat cols = image.size.width;
  19. CGFloat rows = image.size.height;
  20.  
  21. cv::Mat cvMat(rows, cols, CV_8UC4); // 8 bits per component, 4 channels
  22.  
  23. CGContextRef contextRef = CGBitmapContextCreate(cvMat.data, // Pointer to data
  24. cols, // Width of bitmap
  25. rows, // Height of bitmap
  26. , // Bits per component
  27. cvMat.step[], // Bytes per row
  28. colorSpace, // Colorspace
  29. kCGImageAlphaNoneSkipLast |
  30. kCGBitmapByteOrderDefault); // Bitmap info flags
  31.  
  32. CGContextDrawImage(contextRef, CGRectMake(, , cols, rows), image.CGImage);
  33. CGContextRelease(contextRef);
  34. CGColorSpaceRelease(colorSpace);
  35.  
  36. return cvMat;
  37. }
  38.  
  39. // CvMat to UIImage
  40. -(UIImage *)UIImageFromCVMat:(cv::Mat)cvMat
  41. {
  42. NSData *data = [NSData dataWithBytes:cvMat.data length:cvMat.elemSize()*cvMat.total()];
  43. CGColorSpaceRef colorSpace;
  44.  
  45. if (cvMat.elemSize() == ) {
  46. colorSpace = CGColorSpaceCreateDeviceGray();
  47. } else {
  48. colorSpace = CGColorSpaceCreateDeviceRGB();
  49. }
  50.  
  51. CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);
  52.  
  53. // Creating CGImage from cv::Mat
  54. CGImageRef imageRef = CGImageCreate(cvMat.cols, //width
  55. cvMat.rows, //height
  56. , //bits per component
  57. * cvMat.elemSize(), //bits per pixel
  58. cvMat.step[], //bytesPerRow
  59. colorSpace, //colorspace
  60. kCGImageAlphaNone|kCGBitmapByteOrderDefault,// bitmap info
  61. provider, //CGDataProviderRef
  62. NULL, //decode
  63. false, //should interpolate
  64. kCGRenderingIntentDefault //intent
  65. );
  66.  
  67. // Getting UIImage from CGImage
  68. UIImage *finalImage = [UIImage imageWithCGImage:imageRef];
  69. CGImageRelease(imageRef);
  70. CGDataProviderRelease(provider);
  71. CGColorSpaceRelease(colorSpace);
  72.  
  73. return finalImage;
  74. }
  75.  
  76. //由于OpenCV主要针对的是计算机视觉方面的处理,因此在函数库中,最重要的结构体是IplImage结构。
  77. // NOTE you SHOULD cvReleaseImage() for the return value when end of the code.
  78. - (IplImage *)CreateIplImageFromUIImage:(UIImage *)image {
  79. // Getting CGImage from UIImage
  80. CGImageRef imageRef = image.CGImage;
  81.  
  82. CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
  83. // Creating temporal IplImage for drawing
  84. IplImage *iplimage = cvCreateImage(
  85. cvSize(image.size.width,image.size.height), IPL_DEPTH_8U,
  86. );
  87. // Creating CGContext for temporal IplImage
  88. CGContextRef contextRef = CGBitmapContextCreate(
  89. iplimage->imageData, iplimage->width, iplimage->height,
  90. iplimage->depth, iplimage->widthStep,
  91. colorSpace, kCGImageAlphaPremultipliedLast|kCGBitmapByteOrderDefault
  92. );
  93. // Drawing CGImage to CGContext
  94. CGContextDrawImage(
  95. contextRef,
  96. CGRectMake(, , image.size.width, image.size.height),
  97. imageRef
  98. );
  99. CGContextRelease(contextRef);
  100. CGColorSpaceRelease(colorSpace);
  101.  
  102. // Creating result IplImage
  103. IplImage *ret = cvCreateImage(cvGetSize(iplimage), IPL_DEPTH_8U, );
  104. cvCvtColor(iplimage, ret, CV_RGBA2BGR);
  105. cvReleaseImage(&iplimage);
  106.  
  107. return ret;
  108. }
  109.  
  110. // NOTE You should convert color mode as RGB before passing to this function
  111. - (UIImage *)UIImageFromIplImage:(IplImage *)image {
  112. CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
  113. // Allocating the buffer for CGImage
  114. NSData *data =
  115. [NSData dataWithBytes:image->imageData length:image->imageSize];
  116. CGDataProviderRef provider =
  117. CGDataProviderCreateWithCFData((__bridge CFDataRef)data);
  118. // Creating CGImage from chunk of IplImage
  119. CGImageRef imageRef = CGImageCreate(
  120. image->width, image->height,
  121. image->depth, image->depth * image->nChannels, image->widthStep,
  122. colorSpace, kCGImageAlphaNone|kCGBitmapByteOrderDefault,
  123. provider, NULL, false, kCGRenderingIntentDefault
  124. );
  125. // Getting UIImage from CGImage
  126. UIImage *ret = [UIImage imageWithCGImage:imageRef];
  127. CGImageRelease(imageRef);
  128. CGDataProviderRelease(provider);
  129. CGColorSpaceRelease(colorSpace);
  130. return ret;
  131. }
  132.  
  133. #pragma mark - custom method
  134.  
  135. // OSTU算法求出阈值
  136. int Otsu(unsigned char* pGrayImg , int iWidth , int iHeight)
  137. {
  138. if((pGrayImg==)||(iWidth<=)||(iHeight<=))return -;
  139. int ihist[];
  140. int thresholdValue=; // „–÷µ
  141. int n, n1, n2 ;
  142. double m1, m2, sum, csum, fmax, sb;
  143. int i,j,k;
  144. memset(ihist, , sizeof(ihist));
  145. n=iHeight*iWidth;
  146. sum = csum = 0.0;
  147. fmax = -1.0;
  148. n1 = ;
  149. for(i=; i < iHeight; i++)
  150. {
  151. for(j=; j < iWidth; j++)
  152. {
  153. ihist[*pGrayImg]++;
  154. pGrayImg++;
  155. }
  156. }
  157. pGrayImg -= n;
  158. for (k=; k <= ; k++)
  159. {
  160. sum += (double) k * (double) ihist[k];
  161. }
  162. for (k=; k <=; k++)
  163. {
  164. n1 += ihist[k];
  165. if(n1==)continue;
  166. n2 = n - n1;
  167. if(n2==)break;
  168. csum += (double)k *ihist[k];
  169. m1 = csum/n1;
  170. m2 = (sum-csum)/n2;
  171. sb = (double) n1 *(double) n2 *(m1 - m2) * (m1 - m2);
  172. if (sb > fmax)
  173. {
  174. fmax = sb;
  175. thresholdValue = k;
  176. }
  177. }
  178. return(thresholdValue);
  179. }
  180.  
  181. -(UIImage *)Grayimage:(UIImage *)srcimage{
  182. UIImage *resimage;
  183.  
  184. //openCV二值化过程:
  185.  
  186. /*
  187. //1.Src的UIImage -> Src的IplImage
  188. IplImage* srcImage1 = [self CreateIplImageFromUIImage:srcimage];
  189.  
  190. //2.设置Src的IplImage的ImageROI
  191. int width = srcImage1->width;
  192. int height = srcImage1->height;
  193. printf("图片大小%d,%d\n",width,height);
  194.  
  195. // 分割矩形区域
  196. int x = 400;
  197. int y = 1100;
  198. int w = 1200;
  199. int h = 600;
  200.  
  201. //cvSetImageROI:基于给定的矩形设置图像的ROI(感兴趣区域,region of interesting)
  202. cvSetImageROI(srcImage1, cvRect(x, y, w , h));
  203.  
  204. //3.创建新的dstImage1的IplImage,并复制Src的IplImage
  205. IplImage* dstImage1 = cvCreateImage(cvSize(w, h), srcImage1->depth, srcImage1->nChannels);
  206. //cvCopy:如果输入输出数组中的一个是IplImage类型的话,其ROI和COI将被使用。
  207. cvCopy(srcImage1, dstImage1,0);
  208. //cvResetImageROI:释放基于给定的矩形设置图像的ROI(感兴趣区域,region of interesting)
  209. cvResetImageROI(srcImage1);
  210.  
  211. resimage = [self UIImageFromIplImage:dstImage1];
  212. */
  213.  
  214. //4.dstImage1的IplImage转换成cvMat形式的matImage
  215. cv::Mat matImage = [self cvMatFromUIImage:srcimage];
  216.  
  217. cv::Mat matGrey;
  218.  
  219. //5.cvtColor函数对matImage进行灰度处理
  220. //取得IplImage形式的灰度图像
  221. cv::cvtColor(matImage, matGrey, CV_BGR2GRAY);// 转换成灰色
  222.  
  223. //6.使用灰度后的IplImage形式图像,用OSTU算法算阈值:threshold
  224. //IplImage grey = matGrey;
  225.  
  226. resimage = [self UIImageFromCVMat:matGrey];
  227.  
  228. /*
  229. unsigned char* dataImage = (unsigned char*)grey.imageData;
  230. int threshold = Otsu(dataImage, grey.width, grey.height);
  231. printf("阈值:%d\n",threshold);
  232.  
  233. //7.利用阈值算得新的cvMat形式的图像
  234. cv::Mat matBinary;
  235. cv::threshold(matGrey, matBinary, threshold, 255, cv::THRESH_BINARY);
  236.  
  237. //8.cvMat形式的图像转UIImage
  238. UIImage* image = [[UIImage alloc ]init];
  239. image = [self UIImageFromCVMat:matBinary];
  240.  
  241. resimage = image;
  242. */
  243.  
  244. return resimage;
  245. }
  246.  
  247. -(UIImage *)Erzhiimage:(UIImage *)srcimage{
  248.  
  249. UIImage *resimage;
  250.  
  251. //openCV二值化过程:
  252.  
  253. /*
  254. //1.Src的UIImage -> Src的IplImage
  255. IplImage* srcImage1 = [self CreateIplImageFromUIImage:srcimage];
  256.  
  257. //2.设置Src的IplImage的ImageROI
  258. int width = srcImage1->width;
  259. int height = srcImage1->height;
  260. printf("图片大小%d,%d\n",width,height);
  261. //
  262.  
  263. // 分割矩形区域
  264. int x = 400;
  265. int y = 1100;
  266. int w = 1200;
  267. int h = 600;
  268.  
  269. //cvSetImageROI:基于给定的矩形设置图像的ROI(感兴趣区域,region of interesting)
  270. cvSetImageROI(srcImage1, cvRect(x, y, w , h));
  271.  
  272. //3.创建新的dstImage1的IplImage,并复制Src的IplImage
  273. IplImage* dstImage1 = cvCreateImage(cvSize(w, h), srcImage1->depth, srcImage1->nChannels);
  274. //cvCopy:如果输入输出数组中的一个是IplImage类型的话,其ROI和COI将被使用。
  275. cvCopy(srcImage1, dstImage1,0);
  276. //cvResetImageROI:释放基于给定的矩形设置图像的ROI(感兴趣区域,region of interesting)
  277. cvResetImageROI(srcImage1);
  278.  
  279. resimage = [self UIImageFromIplImage:dstImage1];
  280. */
  281.  
  282. //4.dstImage1的IplImage转换成cvMat形式的matImage
  283. cv::Mat matImage = [self cvMatFromUIImage:srcimage];
  284.  
  285. cv::Mat matGrey;
  286.  
  287. //5.cvtColor函数对matImage进行灰度处理
  288. //取得IplImage形式的灰度图像
  289. cv::cvtColor(matImage, matGrey, CV_BGR2GRAY);// 转换成灰色
  290.  
  291. //6.使用灰度后的IplImage形式图像,用OSTU算法算阈值:threshold
  292. IplImage grey = matGrey;
  293. unsigned char* dataImage = (unsigned char*)grey.imageData;
  294. int threshold = Otsu(dataImage, grey.width, grey.height);
  295. printf("阈值:%d\n",threshold);
  296.  
  297. //7.利用阈值算得新的cvMat形式的图像
  298. cv::Mat matBinary;
  299. cv::threshold(matGrey, matBinary, threshold, , cv::THRESH_BINARY);
  300.  
  301. //8.cvMat形式的图像转UIImage
  302. UIImage* image = [[UIImage alloc ]init];
  303. image = [self UIImageFromCVMat:matBinary];
  304.  
  305. resimage = image;
  306.  
  307. return resimage;
  308. }
  309.  
  310. @end

四:可能问题:

  1.出现'list' file not found:   检查类名是否改成.mm了!还不行的话,在Build Phases 中加入库:libc++.dylib 试试。

  2.arm64不支持的问题:在Building settings里Build Active Architecture Only改为No,然后下面Valid Architectures把arm64删了。

五:样例参考:有两个很好的例子,一个是二值,一个是图像匹配。

1.二值 https://github.com/zltqzj/ios_opencv_divide

2.图像匹配 https://github.com/jimple/OpenCVSample

[iOS OpenCV的使用,灰度和二值化]的更多相关文章

  1. OpenCV图像的全局阈值二值化函数(OTSU)

    cv::threshold(GrayImg, Bw, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);//灰度图像二值化 CV_THRESH_OTSU是提取图像最 ...

  2. OpenCV中对图像进行二值化的关键函数——cvThreshold()。

    函数功能:采用Canny方法对图像进行边缘检测 函数原型: void cvThreshold( const CvArr* src, CvArr* dst, double threshold, doub ...

  3. VB6之图像灰度与二值化

    老代码备忘,我对图像处理不是太懂. 注:部分代码引援自网上,话说我到底自己写过什么代码... Private Declare Function GetBitmapBits Lib "gdi3 ...

  4. opencv 对RGB图像直接二值化

    #include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namespace st ...

  5. opencv中对图片的二值化操作并提取特定颜色区域

    一.最近因为所在的实习公司要求用opencv视觉库来写一个对图片识别并提取指定区域的程序.看了很多资料,只学会了皮毛,下面附上简单的代码.运行程序之前需要安装opencv库,官网地址为:https:/ ...

  6. Java基于opencv实现图像数字识别(三)—灰度化和二值化

    Java基于opencv实现图像数字识别(三)-灰度化和二值化 一.灰度化 灰度化:在RGB模型中,如果R=G=B时,则彩色表示灰度颜色,其中R=G=B的值叫灰度值:因此,灰度图像每个像素点只需一个字 ...

  7. OpenCV图像的二值化

    图像的二值化: 与边缘检测相比,轮廓检测有时能更好的反映图像的内容.而要对图像进行轮廓检测,则必须要先对图像进行二值化,图像的二值化就是将图像上的像素点的灰度值设置为0或255,这样将使整个图像呈现出 ...

  8. opencv图像二值化的函数cvThreshold()。 cvAdaptiveThreshol

    OpenCV中对图像进行二值化的关键函数——cvThreshold(). 函数功能:采用Canny方法对图像进行边缘检测 函数原型: void cvThreshold( const CvArr* sr ...

  9. opencv-python图像二值化函数cv2.threshold函数详解及参数cv2.THRESH_OTSU使用

    cv2.threshold()函数的作用是将一幅灰度图二值化,基本用法如下: #ret:暂时就认为是设定的thresh阈值,mask:二值化的图像 ret,mask = cv2.threshold(i ...

随机推荐

  1. Caffe学习系列(23):如何将别人训练好的model用到自己的数据上

    caffe团队用imagenet图片进行训练,迭代30多万次,训练出来一个model.这个model将图片分为1000类,应该是目前为止最好的图片分类model了. 假设我现在有一些自己的图片想进行分 ...

  2. Java程序设计的DOS命令基础

    Java程序设计的DOS命令基础 用户使用操作系统和软件有两种方式:命令行界面(Command Line Interface,CLI)和图形界面(Graphical User Interface,GU ...

  3. Word 打包 zip 并提供下载

    该篇博客记录Java Web项目将word打包zip并提供下载功能的实现和其中遇到的坑,方便后续自己的查看的参照. 1. 后台处理的java 方法 首先将所有的word生成到uploadword目录下 ...

  4. Python2.6-原理之类和oop(下)

    来自<python学习手册第四版>第六部分 五.运算符重载(29章) 这部分深入介绍更多的细节并看一些常用的重载方法,虽然不会展示每种可用的运算符重载方法,但是这里给出的代码也足够覆盖py ...

  5. C# 7.0 新特性1: 基于Tuple的“多”返回值方法

    本文基于Roslyn项目中的Issue:#347 展开讨论. 1. C# 7.0 新特性1: 基于Tuple的“多”返回值方法 2. C# 7.0 新特性2: 本地方法 3. C# 7.0 新特性3: ...

  6. 【python游戏编程之旅】第七篇---pygame中的冲突检测技术

    本系列博客介绍以python+pygame库进行小游戏的开发.有写的不对之处还望各位海涵. 上一个博客我们一起学习了pygame中的Sprite模块和如何加载动画:http://www.cnblogs ...

  7. 匈牙利算法(codevs2776)

    type node=^link; link=record des:longint; next:node; end; var n,m,i,t,num:longint; p:node; nd:..] of ...

  8. [cross domain] four approachs to cross domain in javascript

    four approachs can cross domain in javascript 1.jsonp 2.document.domain(only in frame and they have ...

  9. Beta版本冲刺———第六天

    会议照片: 项目燃尽图: 1.项目进展: 该项目的Beta版本冲刺到今天就大体结束,但是小组依然困在"如何保存每次游戏的分数,并将其排序列在排行榜中"的问题上,小组四个人都在一起解 ...

  10. 转 为什么文件存储要选用B+树这样的数据结构?

    为什么文件存储要选用B+树这样的数据结构? "文件存储要选用B+树这样的数据结构"--没记错的话,这是严蔚敏那本数据结构书上的一句结论.不知道是我没细看还是她没细讲,反正当时纯粹应 ...