[iOS OpenCV的使用,灰度和二值化]
看网上方法很多,但版本都不够新,我看了网上一些知识,总结了下,来个最新版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
//
// Imageprocess.h
// Chepaishibie
//
// Created by shen on 15/1/28.
// Copyright (c) 2015年 shen. All rights reserved.
// #import <Foundation/Foundation.h>
#import <opencv2/opencv.hpp>
#import <UIKit/UIKit.h> @interface Imageprocess : UIViewController - (cv::Mat)cvMatFromUIImage:(UIImage *)image; - (UIImage *)UIImageFromCVMat:(cv::Mat)cvMat; - (IplImage *)CreateIplImageFromUIImage:(UIImage *)image; - (UIImage *)UIImageFromIplImage:(IplImage *)image; - (UIImage *)Grayimage:(UIImage *)srcimage; - (UIImage *)Erzhiimage:(UIImage *)srcimage; int Otsu(unsigned char* pGrayImg , int iWidth , int iHeight); @end
Imageprocess.mm 里面包含了很多函数:
主要是 UIImage->cv::Mat ,cv::Mat->UIImage,UIImage->IplImage,IplImage->UIImage, 灰度化,二值化等,还有个OSTU计算阈值的方法。
//
// Imageprocess.mm
// Chepaishibie
//
// Created by shen on 15/1/28.
// Copyright (c) 2015年 shen. All rights reserved.
// #import "Imageprocess.h" @implementation Imageprocess #pragma mark - opencv method
// 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 CGContextRef contextRef = CGBitmapContextCreate(cvMat.data, // Pointer to data
cols, // Width of bitmap
rows, // Height of bitmap
, // Bits per component
cvMat.step[], // Bytes per row
colorSpace, // Colorspace
kCGImageAlphaNoneSkipLast |
kCGBitmapByteOrderDefault); // Bitmap info flags CGContextDrawImage(contextRef, CGRectMake(, , cols, rows), image.CGImage);
CGContextRelease(contextRef);
CGColorSpaceRelease(colorSpace); return cvMat;
} // CvMat to UIImage
-(UIImage *)UIImageFromCVMat:(cv::Mat)cvMat
{
NSData *data = [NSData dataWithBytes:cvMat.data length:cvMat.elemSize()*cvMat.total()];
CGColorSpaceRef colorSpace; if (cvMat.elemSize() == ) {
colorSpace = CGColorSpaceCreateDeviceGray();
} else {
colorSpace = CGColorSpaceCreateDeviceRGB();
} CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data); // Creating CGImage from cv::Mat
CGImageRef imageRef = CGImageCreate(cvMat.cols, //width
cvMat.rows, //height
, //bits per component
* cvMat.elemSize(), //bits per pixel
cvMat.step[], //bytesPerRow
colorSpace, //colorspace
kCGImageAlphaNone|kCGBitmapByteOrderDefault,// bitmap info
provider, //CGDataProviderRef
NULL, //decode
false, //should interpolate
kCGRenderingIntentDefault //intent
); // Getting UIImage from CGImage
UIImage *finalImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
CGDataProviderRelease(provider);
CGColorSpaceRelease(colorSpace); return finalImage;
} //由于OpenCV主要针对的是计算机视觉方面的处理,因此在函数库中,最重要的结构体是IplImage结构。
// NOTE you SHOULD cvReleaseImage() for the return value when end of the code.
- (IplImage *)CreateIplImageFromUIImage:(UIImage *)image {
// Getting CGImage from UIImage
CGImageRef imageRef = image.CGImage; CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
// Creating temporal IplImage for drawing
IplImage *iplimage = cvCreateImage(
cvSize(image.size.width,image.size.height), IPL_DEPTH_8U,
);
// Creating CGContext for temporal IplImage
CGContextRef contextRef = CGBitmapContextCreate(
iplimage->imageData, iplimage->width, iplimage->height,
iplimage->depth, iplimage->widthStep,
colorSpace, kCGImageAlphaPremultipliedLast|kCGBitmapByteOrderDefault
);
// Drawing CGImage to CGContext
CGContextDrawImage(
contextRef,
CGRectMake(, , image.size.width, image.size.height),
imageRef
);
CGContextRelease(contextRef);
CGColorSpaceRelease(colorSpace); // Creating result IplImage
IplImage *ret = cvCreateImage(cvGetSize(iplimage), IPL_DEPTH_8U, );
cvCvtColor(iplimage, ret, CV_RGBA2BGR);
cvReleaseImage(&iplimage); return ret;
} // NOTE You should convert color mode as RGB before passing to this function
- (UIImage *)UIImageFromIplImage:(IplImage *)image {
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
// Allocating the buffer for CGImage
NSData *data =
[NSData dataWithBytes:image->imageData length:image->imageSize];
CGDataProviderRef provider =
CGDataProviderCreateWithCFData((__bridge CFDataRef)data);
// Creating CGImage from chunk of IplImage
CGImageRef imageRef = CGImageCreate(
image->width, image->height,
image->depth, image->depth * image->nChannels, image->widthStep,
colorSpace, kCGImageAlphaNone|kCGBitmapByteOrderDefault,
provider, NULL, false, kCGRenderingIntentDefault
);
// Getting UIImage from CGImage
UIImage *ret = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
CGDataProviderRelease(provider);
CGColorSpaceRelease(colorSpace);
return ret;
} #pragma mark - custom method // OSTU算法求出阈值
int Otsu(unsigned char* pGrayImg , int iWidth , int iHeight)
{
if((pGrayImg==)||(iWidth<=)||(iHeight<=))return -;
int ihist[];
int thresholdValue=; // „–÷µ
int n, n1, n2 ;
double m1, m2, sum, csum, fmax, sb;
int i,j,k;
memset(ihist, , sizeof(ihist));
n=iHeight*iWidth;
sum = csum = 0.0;
fmax = -1.0;
n1 = ;
for(i=; i < iHeight; i++)
{
for(j=; j < iWidth; j++)
{
ihist[*pGrayImg]++;
pGrayImg++;
}
}
pGrayImg -= n;
for (k=; k <= ; k++)
{
sum += (double) k * (double) ihist[k];
}
for (k=; k <=; k++)
{
n1 += ihist[k];
if(n1==)continue;
n2 = n - n1;
if(n2==)break;
csum += (double)k *ihist[k];
m1 = csum/n1;
m2 = (sum-csum)/n2;
sb = (double) n1 *(double) n2 *(m1 - m2) * (m1 - m2);
if (sb > fmax)
{
fmax = sb;
thresholdValue = k;
}
}
return(thresholdValue);
} -(UIImage *)Grayimage:(UIImage *)srcimage{
UIImage *resimage; //openCV二值化过程: /*
//1.Src的UIImage -> Src的IplImage
IplImage* srcImage1 = [self CreateIplImageFromUIImage:srcimage]; //2.设置Src的IplImage的ImageROI
int width = srcImage1->width;
int height = srcImage1->height;
printf("图片大小%d,%d\n",width,height); // 分割矩形区域
int x = 400;
int y = 1100;
int w = 1200;
int h = 600; //cvSetImageROI:基于给定的矩形设置图像的ROI(感兴趣区域,region of interesting)
cvSetImageROI(srcImage1, cvRect(x, y, w , h)); //3.创建新的dstImage1的IplImage,并复制Src的IplImage
IplImage* dstImage1 = cvCreateImage(cvSize(w, h), srcImage1->depth, srcImage1->nChannels);
//cvCopy:如果输入输出数组中的一个是IplImage类型的话,其ROI和COI将被使用。
cvCopy(srcImage1, dstImage1,0);
//cvResetImageROI:释放基于给定的矩形设置图像的ROI(感兴趣区域,region of interesting)
cvResetImageROI(srcImage1); resimage = [self UIImageFromIplImage:dstImage1];
*/ //4.dstImage1的IplImage转换成cvMat形式的matImage
cv::Mat matImage = [self cvMatFromUIImage:srcimage]; cv::Mat matGrey; //5.cvtColor函数对matImage进行灰度处理
//取得IplImage形式的灰度图像
cv::cvtColor(matImage, matGrey, CV_BGR2GRAY);// 转换成灰色 //6.使用灰度后的IplImage形式图像,用OSTU算法算阈值:threshold
//IplImage grey = matGrey; resimage = [self UIImageFromCVMat:matGrey]; /*
unsigned char* dataImage = (unsigned char*)grey.imageData;
int threshold = Otsu(dataImage, grey.width, grey.height);
printf("阈值:%d\n",threshold); //7.利用阈值算得新的cvMat形式的图像
cv::Mat matBinary;
cv::threshold(matGrey, matBinary, threshold, 255, cv::THRESH_BINARY); //8.cvMat形式的图像转UIImage
UIImage* image = [[UIImage alloc ]init];
image = [self UIImageFromCVMat:matBinary]; resimage = image;
*/ return resimage;
} -(UIImage *)Erzhiimage:(UIImage *)srcimage{ UIImage *resimage; //openCV二值化过程: /*
//1.Src的UIImage -> Src的IplImage
IplImage* srcImage1 = [self CreateIplImageFromUIImage:srcimage]; //2.设置Src的IplImage的ImageROI
int width = srcImage1->width;
int height = srcImage1->height;
printf("图片大小%d,%d\n",width,height);
// // 分割矩形区域
int x = 400;
int y = 1100;
int w = 1200;
int h = 600; //cvSetImageROI:基于给定的矩形设置图像的ROI(感兴趣区域,region of interesting)
cvSetImageROI(srcImage1, cvRect(x, y, w , h)); //3.创建新的dstImage1的IplImage,并复制Src的IplImage
IplImage* dstImage1 = cvCreateImage(cvSize(w, h), srcImage1->depth, srcImage1->nChannels);
//cvCopy:如果输入输出数组中的一个是IplImage类型的话,其ROI和COI将被使用。
cvCopy(srcImage1, dstImage1,0);
//cvResetImageROI:释放基于给定的矩形设置图像的ROI(感兴趣区域,region of interesting)
cvResetImageROI(srcImage1); resimage = [self UIImageFromIplImage:dstImage1];
*/ //4.dstImage1的IplImage转换成cvMat形式的matImage
cv::Mat matImage = [self cvMatFromUIImage:srcimage]; cv::Mat matGrey; //5.cvtColor函数对matImage进行灰度处理
//取得IplImage形式的灰度图像
cv::cvtColor(matImage, matGrey, CV_BGR2GRAY);// 转换成灰色 //6.使用灰度后的IplImage形式图像,用OSTU算法算阈值:threshold
IplImage grey = matGrey;
unsigned char* dataImage = (unsigned char*)grey.imageData;
int threshold = Otsu(dataImage, grey.width, grey.height);
printf("阈值:%d\n",threshold); //7.利用阈值算得新的cvMat形式的图像
cv::Mat matBinary;
cv::threshold(matGrey, matBinary, threshold, , cv::THRESH_BINARY); //8.cvMat形式的图像转UIImage
UIImage* image = [[UIImage alloc ]init];
image = [self UIImageFromCVMat:matBinary]; resimage = image; return resimage;
} @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的使用,灰度和二值化]的更多相关文章
- OpenCV图像的全局阈值二值化函数(OTSU)
cv::threshold(GrayImg, Bw, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);//灰度图像二值化 CV_THRESH_OTSU是提取图像最 ...
- OpenCV中对图像进行二值化的关键函数——cvThreshold()。
函数功能:采用Canny方法对图像进行边缘检测 函数原型: void cvThreshold( const CvArr* src, CvArr* dst, double threshold, doub ...
- VB6之图像灰度与二值化
老代码备忘,我对图像处理不是太懂. 注:部分代码引援自网上,话说我到底自己写过什么代码... Private Declare Function GetBitmapBits Lib "gdi3 ...
- opencv 对RGB图像直接二值化
#include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namespace st ...
- opencv中对图片的二值化操作并提取特定颜色区域
一.最近因为所在的实习公司要求用opencv视觉库来写一个对图片识别并提取指定区域的程序.看了很多资料,只学会了皮毛,下面附上简单的代码.运行程序之前需要安装opencv库,官网地址为:https:/ ...
- Java基于opencv实现图像数字识别(三)—灰度化和二值化
Java基于opencv实现图像数字识别(三)-灰度化和二值化 一.灰度化 灰度化:在RGB模型中,如果R=G=B时,则彩色表示灰度颜色,其中R=G=B的值叫灰度值:因此,灰度图像每个像素点只需一个字 ...
- OpenCV图像的二值化
图像的二值化: 与边缘检测相比,轮廓检测有时能更好的反映图像的内容.而要对图像进行轮廓检测,则必须要先对图像进行二值化,图像的二值化就是将图像上的像素点的灰度值设置为0或255,这样将使整个图像呈现出 ...
- opencv图像二值化的函数cvThreshold()。 cvAdaptiveThreshol
OpenCV中对图像进行二值化的关键函数——cvThreshold(). 函数功能:采用Canny方法对图像进行边缘检测 函数原型: void cvThreshold( const CvArr* sr ...
- opencv-python图像二值化函数cv2.threshold函数详解及参数cv2.THRESH_OTSU使用
cv2.threshold()函数的作用是将一幅灰度图二值化,基本用法如下: #ret:暂时就认为是设定的thresh阈值,mask:二值化的图像 ret,mask = cv2.threshold(i ...
随机推荐
- 编写更少量的代码:使用apache commons工具类库
Commons-configuration Commons-FileUpload Commons DbUtils Commons BeanUtils Commons CLI Commo ...
- Oracle 常见错误排查
1. java.sql.SQLException: ORA-01000: 超出打开游标的最大数 step 1: 查看数据库当前的游标数配置slqplus:show parameter open_cur ...
- 大新闻!HoloLens即将入华商用
昨天微软搞了大新闻,Terry和Alexi到了深圳,在WinHEC大会上宣布了2017上半年HoloLens正式入华商用. 关于HoloLens的技术原理和细节官方文档和报道已经披露很多了,他是一款真 ...
- JVM内存管理------JAVA语言的内存管理概述
引言 内存管理一直是JAVA语言自豪与骄傲的资本,它让JAVA程序员基本上可以彻底忽略与内存管理相关的细节,只专注于业务逻辑.不过世界上不存在十全十美的好事,在带来了便利的同时,也因此引入了很多令人抓 ...
- 37-wc 简明笔记
显示行数.单词数和字节数 wc [options] [file-list] 参数 file-list是wc分析的一个或多个文件的路径名列表.如果省略file-list,wc就从标准输入中读取输入 选项 ...
- 大规模数据 从SQL SERVER导入到ORACLE方法
来源于:http://blog.csdn.net/iitkd/article/details/40394789 来源:一个7G的SQL SERVER .bak文件要导入到Oracle中,经过实验,完成 ...
- 转 漫谈linux文件IO
在Linux 开发中,有几个关系到性能的东西,技术人员非常关注:进程,CPU,MEM,网络IO,磁盘IO.本篇文件打算详细全面,深入浅出.剖析文件IO的细节.从多个角度探索如何提高IO性能.本文尽量用 ...
- Windows配置mycat
MyCat使用Mysql的通讯协议模拟成一个MySQl服务器,并建立了完整的Schema(数据库).Table(数据表).User(用户)的逻辑模型,并将这套逻辑模型映射到后端的存储节点DataNod ...
- javascript获得客户端IP的又一方法
<script language="JavaScript">VIH_BackColor = "palegreen";VIH_ForeColor = ...
- openwrt的环境搭建、定制和编译
参考1:编译openwrt全过程 参考2: ARM9的OpenWRT系统的移植以及 无线视觉操控系统的软件开发 参考3:搭建OpenWrt开发环境(包括编译过程) 参考4:各个openwrt版本的sv ...