OpenCV??iOS?圖像處理編程入門(mén)詳細(xì)教程
OpenCV簡(jiǎn)介
OpenCV(Open Source Computer Vision Library) 是一個(gè)廣受歡迎的開(kāi)源的跨平臺(tái)計(jì)算機(jī)視覺(jué)庫(kù),它實(shí)現(xiàn)了圖像處理和計(jì)算機(jī)視覺(jué)方面的很多通用算法,算法從最基本的濾波到高級(jí)的物體檢測(cè)皆有涵蓋。
多語(yǔ)言接口
OpenCV 使用 C/C++ 開(kāi)發(fā),同時(shí)也提供了 Python、Java、MATLAB 等其他語(yǔ)言的接口。
跨平臺(tái)
OpenCV 是跨平臺(tái)的,可以在 Windows、Linux、Mac OS、Android、iOS 等操作系統(tǒng)上運(yùn)行。
應(yīng)用領(lǐng)域廣泛
OpenCV 的應(yīng)用領(lǐng)域非常廣泛,包括圖像拼接、圖像降噪、產(chǎn)品質(zhì)檢、人機(jī)交互、人臉識(shí)別、動(dòng)作識(shí)別、動(dòng)作跟蹤、無(wú)人駕駛等。OpenCV 還提供了機(jī)器學(xué)習(xí)模塊,你可以使用正態(tài)貝葉斯、K最近鄰、支持向量機(jī)、決策樹(shù)、隨機(jī)森林、人工神經(jīng)網(wǎng)絡(luò)等機(jī)器學(xué)習(xí)算法。
集成OpenCV
1、首先創(chuàng)建一個(gè)Xcode 工程, 在Build Settings 設(shè)置BuEnable Bitcode 為NO。
2、使用 cocoaPads 配置OpenCV。打開(kāi)終端,cd到項(xiàng)目的目錄,執(zhí)行pod init 命令初始化工程,創(chuàng)建工程對(duì)應(yīng)的Podfile文件。使用 vim Podfile 添加 pod 'OpenCV' ,'~> 4.3.0',最后執(zhí)行pod install安裝OpenCV。
3、所引用到OpenCV 的類(lèi)文件,需要將m文件改成.mm,告訴編譯器有C++。
基礎(chǔ)圖像容器Mat
圖像表示
通常我們拍攝的現(xiàn)實(shí)世界中的真實(shí)的圖像,在轉(zhuǎn)化到電子設(shè)備中時(shí),記錄的卻是圖像中的每個(gè)點(diǎn)的數(shù)值。
一副尺寸為A x B的圖像,可以用AxB的矩陣來(lái)表示,矩陣元素的值表示這個(gè)位置上的像素的亮度,一般來(lái)說(shuō)像素值越大表示該點(diǎn)越亮。
一般情況,灰度圖用 2 維矩陣表示,彩色(多通道)圖像用 3 維矩陣(M × N × 3)表示。對(duì)于圖像顯示來(lái)說(shuō),目前大部分設(shè)備都是用無(wú)符號(hào) 8 位整數(shù)(類(lèi)型為 CV_8U)表示像素亮度。
圖像數(shù)據(jù)在計(jì)算機(jī)內(nèi)存中的存儲(chǔ)順序?yàn)橐詧D像最左上點(diǎn)(也可能是最左下 點(diǎn))開(kāi)始,如果是多通道圖像,比如 RGB 圖像,則每個(gè) 像素用三個(gè)字節(jié)表示。在 OpenCV 中,RGB 圖像的通道順序?yàn)?BGR 。
Mat類(lèi)關(guān)鍵屬性及定義
其中關(guān)鍵的屬性如下:
/* flag參數(shù)中包含許多關(guān)于矩陣的信息,如: -Mat 的標(biāo)識(shí)
-數(shù)據(jù)是否連續(xù) -深度 -通道數(shù)目
*/
int flags;
//矩陣的維數(shù),取值應(yīng)該大于或等于 2
int dims;
//矩陣的行數(shù)和列數(shù),如果矩陣超過(guò) 2 維,這兩個(gè)變量的值都為-1
int rows, cols;
//指向數(shù)據(jù)的指針
uchar* data;
//指向引用計(jì)數(shù)的指針 //如果數(shù)據(jù)是由用戶(hù)分配的,則為 NULL
int* refcount;
Mat定義如下:
class CV_EXPORTS Mat
{
public:
Mat();
Mat(int rows, int cols, int type);
Mat(Size size, int type);
Mat(int rows, int cols, int type, const Scalar& s);
Mat(Size size, int type, const Scalar& s);
Mat(int ndims, const int* sizes, int type);
Mat(const std::vector<int>& sizes, int type);
Mat(int ndims, const int* sizes, int type, const Scalar& s);
Mat(const std::vector<int>& sizes, int type, const Scalar& s);
Mat(const Mat& m);
Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP);
Mat(Size size, int type, void* data, size_t step=AUTO_STEP);
.......
.........................
................................
/*! includes several bit-fields:
- the magic signature
- continuity flag
- depth
- number of channels
*/
int flags;
//! the matrix dimensionality, >= 2
int dims;
//! the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions
int rows, cols;
//! pointer to the data
uchar* data;
//! helper fields used in locateROI and adjustROI
const uchar* datastart;
const uchar* dataend;
const uchar* datalimit;
//! custom allocator
MatAllocator* allocator;
//! and the standard allocator
static MatAllocator* getStdAllocator();
static MatAllocator* getDefaultAllocator();
static void setDefaultAllocator(MatAllocator* allocator);
//! internal use method: updates the continuity flag
void updateContinuityFlag();
//! interaction with UMat
UMatData* u;
MatSize size;
MatStep step;
protected:
template<typename _Tp, typename Functor> void forEach_impl(const Functor& operation);
};創(chuàng)建Mat對(duì)象
Mat 是一個(gè)非常優(yōu)秀的圖像類(lèi),它同時(shí)也是一個(gè)通用的矩陣類(lèi),可以用來(lái)創(chuàng)建和操作多維矩陣。有多種方法創(chuàng)建一個(gè) Mat 對(duì)象。
對(duì)于二維多通道圖像,首先要定義其尺寸,即行數(shù)和列數(shù)。而后需要指定存儲(chǔ)元素的數(shù)據(jù)類(lèi)型以及每個(gè)矩陣點(diǎn)的通道數(shù)。為此,定義規(guī)則如下:
CV_【位數(shù)】【帶符號(hào)與否】【類(lèi)型前綴】C【通道數(shù)】
例:CV_8UC3:表示使用8位的unsigned char類(lèi)型,每個(gè)像素有三個(gè)元素組成三通道。而預(yù)先定義的通道數(shù)可以多達(dá)四個(gè)。Scalar 是個(gè)short 類(lèi)型的向量,能使用指定的定制化值來(lái)初始化矩陣,它還可以表示顏色。
1、構(gòu)造函數(shù)方法創(chuàng)建Mat
Mat M(5,8, CV_8UC3, Scalar(255,0,0));
創(chuàng)建一個(gè)高度為5,寬度為8的圖像,圖像元素為8位無(wú)符號(hào)類(lèi)型,且有3個(gè)通道。圖像的所有像素值被初始化為(255,0,0)。因 OpenCV 中默認(rèn)的顏色順序?yàn)?BGR,因此這是一個(gè)純藍(lán)色的圖像【RGB為:(0,0,255)】
//創(chuàng)建行數(shù)為 rows,列數(shù)為 col,類(lèi)型為 type 的圖像; Mat::Mat(int rows, int cols, int type); //創(chuàng)建大小為 size,類(lèi)型為 type 的圖像; Mat::Mat(Size size, int type) //創(chuàng)建行數(shù)為 rows,列數(shù)為 col,類(lèi)型為 type 的圖像,并將所有元素初始 化為值 s; Mat::Mat(int rows, int cols, int type, const Scalar& s); //創(chuàng)建大小為 size,類(lèi)型為 type 的圖像,并將所有元素初始化為值 s; Mat::Mat(Size size, int type, const Scalar& s);
2、利用Create()函數(shù)創(chuàng)建Mat
Mat mat; mat.create(2, 2, CV_8UC3);
常用數(shù)據(jù)結(jié)構(gòu)和函數(shù)
Point類(lèi)
用于表示點(diǎn)。Point類(lèi)數(shù)據(jù)結(jié)構(gòu)表示了二維坐標(biāo)系下的點(diǎn),即由其圖像坐標(biāo)x和y指定的2D點(diǎn)。
使用方式如下:
Point point; point.x=2; point.y=5; 或 Point point=Point(2,5);
Scalar類(lèi)
用于表示顏色的。Scalar()表示具有4個(gè)元素的數(shù)組,在OpenCV中被大量用于傳遞像素值,如RGB顏色值。RGB顏色值為三個(gè)參數(shù),對(duì)于Scalar()來(lái)說(shuō),第四個(gè)參數(shù)為可選,用不到則無(wú)需寫(xiě)出,只寫(xiě)三個(gè)參數(shù),則OpenCV會(huì)認(rèn)為我們就想表示三個(gè)參數(shù)。
例:
Scalar scalar=Scalar(0,2,255);
定義的RGB顏色值為:0:藍(lán)色分量,2:綠色分量,255:紅色分量。
Scalar類(lèi)的源頭為Scalar_類(lèi),而Scalar_類(lèi)為Vec4x 的一個(gè)變種,常用的Scalar其實(shí)就是 Scalar_<double> ,這也是為啥很多函數(shù)的參數(shù)可以輸入Mat,也可以是Scalar。
//Vec 是Matx的一個(gè)派生類(lèi),一個(gè)一維的Matx,和vector很類(lèi)似。Matx是個(gè)輕量級(jí)的Mat,必須在使用前規(guī)定好大小。
template<typename _Tp> class Scalar_ : public Vec<_Tp, 4>
{
public:
//! default constructor
Scalar_();
Scalar_(_Tp v0, _Tp v1, _Tp v2=0, _Tp v3=0);
Scalar_(_Tp v0);
Scalar_(const Scalar_& s);
Scalar_(Scalar_&& s) CV_NOEXCEPT;
Scalar_& operator=(const Scalar_& s);
Scalar_& operator=(Scalar_&& s) CV_NOEXCEPT;
template<typename _Tp2, int cn>
Scalar_(const Vec<_Tp2, cn>& v);
//! returns a scalar with all elements set to v0
static Scalar_<_Tp> all(_Tp v0);
//! conversion to another data type
template<typename T2> operator Scalar_<T2>() const;
//! per-element product
Scalar_<_Tp> mul(const Scalar_<_Tp>& a, double scale=1 ) const;
//! returns (v0, -v1, -v2, -v3)
Scalar_<_Tp> conj() const;
//! returns true iff v1 == v2 == v3 == 0
bool isReal() const;
};
typedef Scalar_<double> Scalar;Size類(lèi)
用于表示尺寸。Size類(lèi)部分源代碼如下:
typedef Size_<int> Size2i; typedef Size_<int64> Size2l; typedef Size_<float> Size2f; typedef Size_<double> Size2d; typedef Size2i Size;
其中Size_是模版類(lèi),在此,Size_<int> 表示其類(lèi)內(nèi)部的模版所代表的類(lèi)型為int。意思是:首先給已知的數(shù)據(jù)類(lèi)型Size_<int> 起個(gè)新名字為Size2i,然后又給已知的數(shù)據(jù)類(lèi)型Size2i 起個(gè)新名字Size。因此,Size_<int> 、Size2i、Size三個(gè)類(lèi)型名等價(jià)。
Size_模版定義如下:
template<typename _Tp> class Size_
{
public:
typedef _Tp value_type;
//! default constructor
//構(gòu)造函數(shù)
Size_();
Size_(_Tp _width, _Tp _height);
Size_(const Size_& sz);
Size_(Size_&& sz) CV_NOEXCEPT;
Size_(const Point_<_Tp>& pt);
Size_& operator = (const Size_& sz);
Size_& operator = (Size_&& sz) CV_NOEXCEPT;
//! the area (width*height)
//區(qū)域(width*height)
_Tp area() const;
//! aspect ratio (width/height)
double aspectRatio() const;
//! true if empty
bool empty() const;
//! conversion of another data type.
//轉(zhuǎn)化為另一種數(shù)據(jù)類(lèi)型
template<typename _Tp2> operator Size_<_Tp2>() const;
//常用屬性,模版類(lèi)型的寬度和高度
_Tp width; //!< the width 寬度
_Tp height; //!< the height高度
};Size_模版類(lèi)內(nèi)部又重載了一些構(gòu)造函數(shù),使用度最高的構(gòu)造函數(shù)如下:
Size_(_Tp _width, _Tp _height);
于是我們可以用xx.width和xx.height 來(lái)分別表示寬和高。
例:Size(2,3);構(gòu)造出的Size寬為2,高為3。即 size.width=2, size.height=3。
Size size=Size(2,3); size.width; size.height;
Rect類(lèi)
用于表示矩形。Rect 類(lèi)的成員變量有x,y,width,height,分別為左上角點(diǎn)點(diǎn)坐標(biāo)和矩形的寬和高。常用的成員函數(shù)有Size(),返回值為Size;area()返回矩形的面積;contains(Point)判斷點(diǎn)是否位于矩形內(nèi);inside(Rect)函數(shù)判斷矩形是否在該矩形內(nèi);tl()返回左上角點(diǎn)坐標(biāo);br()返回右下角點(diǎn)坐標(biāo)。如想求兩個(gè)矩形的交集和并集,可如下這么寫(xiě):
Rect rect1=Rect(0,0,100,120); Rect rect2=Rect(10,10,100,120); Rect rect=rect1|rect2; Rect rect3=rect1&rect2;
若想讓矩形進(jìn)行平移或縮放操作,可這樣:
Rect rect=Rect(10,10,100,120); Rect rect1=rect+point; Rect rect2=rect+size;
cvtColor類(lèi)
用于顏色空間轉(zhuǎn)換。cvtColor()函數(shù)是OpenCV里的顏色空間轉(zhuǎn)換函數(shù),可以實(shí)現(xiàn)RGB向HSV 、HSI等顏色空間的轉(zhuǎn)換,可以轉(zhuǎn)換為灰度圖像。
cvtColor()函數(shù)定義如下:
CV_EXPORTS_W void cvtColor( InputArray src, OutputArray dst, int code, int dstCn = 0 );
第1個(gè)參數(shù)src為輸入圖像,第2個(gè)參數(shù)dst為輸出圖像,第3個(gè)參數(shù)code為顏色空間轉(zhuǎn)換的標(biāo)識(shí)符,第4個(gè)參數(shù)dstCn為目標(biāo)圖像的通道數(shù),若參數(shù)是0,表示目標(biāo)圖像取源圖像的通道數(shù)。
例:轉(zhuǎn)換源圖片為灰度圖片
cvtColor(matInput, grayMat,COLOR_BGR2GRAY);
顏色空間轉(zhuǎn)換標(biāo)識(shí)符在OpenCV 庫(kù)中的imgproc.hpp 中的ColorConversionCodes 枚舉中定義了很多標(biāo)識(shí)符。
/** the color conversion codes
@see @ref imgproc_color_conversions
@ingroup imgproc_color_conversions
*/
enum ColorConversionCodes {
COLOR_BGR2BGRA = 0, //!< add alpha channel to RGB or BGR image
COLOR_RGB2RGBA = COLOR_BGR2BGRA,
COLOR_BGRA2BGR = 1, //!< remove alpha channel from RGB or BGR image
COLOR_RGBA2RGB = COLOR_BGRA2BGR,
COLOR_BGR2RGBA = 2, //!< convert between RGB and BGR color spaces (with or without alpha channel)
COLOR_RGB2BGRA = COLOR_BGR2RGBA,
COLOR_RGBA2BGR = 3,
COLOR_BGRA2RGB = COLOR_RGBA2BGR,
...........
...................
..............................
//! Demosaicing with alpha channel
COLOR_BayerBG2BGRA = 139,
COLOR_BayerGB2BGRA = 140,
COLOR_BayerRG2BGRA = 141,
COLOR_BayerGR2BGRA = 142,
COLOR_BayerBG2RGBA = COLOR_BayerRG2BGRA,
COLOR_BayerGB2RGBA = COLOR_BayerGR2BGRA,
COLOR_BayerRG2RGBA = COLOR_BayerBG2BGRA,
COLOR_BayerGR2RGBA = COLOR_BayerGB2BGRA,
COLOR_COLORCVT_MAX = 143
};圖像處理技術(shù)
訪(fǎng)問(wèn)圖像中的像素
我們已經(jīng)了解到圖像矩陣的大小取決于所用的顏色模型,準(zhǔn)確的說(shuō)取決于所用的通道數(shù)。如果是灰度圖像,矩陣如下:
| c 0 | c 1 | c ... | c m | |
|---|---|---|---|---|
| R 0 | 0,0 | 0,1 | ... | 0,m |
| R 1 | 1,0 | 1,1 | ... | 1,m |
| R ... | ...,0 | ...,1 | ... | ...,m |
| R n | n,0 | n,1 | n,.. | n,m |
多通道圖來(lái)說(shuō),矩陣中列會(huì)包含多個(gè)子列,其子列個(gè)數(shù)與通道數(shù)相等。
例:下面表示RGB 顏色模型的矩陣。
| c 0 | c 1 | c ... | c m | |
|---|---|---|---|---|
| R 0 | 0,0 0,0 0,0 | 0,1 0,1 0,1 | ... ... ... | 0,m 0,m 0,m |
| R 1 | 1,0 1,0 1,0 | 1,1 1,1 1,1 | ... ... ... | 1,m 1,m 1,m |
| R ... | ...,0 ...,0 ...,0 | ...,1 ...,1 ...,1 | ... ... ... | ...,m ...,m ...,m |
| R n | n,0 n,0 n,0 | n,1 n,1 n,1 | n,.. n,.. n,.. | n,m n,m n,m |
值得注意的是,OpenCV中子列的通道順序是反過(guò)來(lái)的,是BGR 而不是RGB。
任何圖像處理算法,都是從操作每個(gè)像素開(kāi)始的。OpenCV中提供了三種訪(fǎng)問(wèn)每個(gè)像素的方法。
指針訪(fǎng)問(wèn):
指針訪(fǎng)問(wèn)像素利用的是C語(yǔ)言中的操作符[]。這種最快。
//顏色空間縮減
void colorReduce(Mat& matInput,Mat& matoutput,int div){
//復(fù)制輸入圖像
matoutput=matInput.clone();
int rows=matoutput.rows;//行數(shù),高度
int cols=matoutput.cols*matoutput.channels();//列數(shù)*通道數(shù)=每一行元素的個(gè)數(shù)
//遍歷圖像矩陣//寬度
for (int i=0; i<rows; i++) {//行循環(huán)
uchar *data=matoutput.ptr<uchar>(i);//取出第i行首地址
for (int j=0; j<cols; j++) {//列循環(huán)
data[j]=data[j]/div*div+div/2;//開(kāi)始處理每一個(gè)像素
}
}
}Mat類(lèi)中的公有成員變量rows為圖像的高度,cols是寬度。channels()函數(shù)返回圖像的通道數(shù)。灰度通道是1,彩色通道數(shù)為3,含alpha的為4。ptr<uchar>(i)可以得到圖像任意行的首地址。ptr是模版函數(shù),返回第i行的首地址。
迭代器iterator:
在迭代法中,僅僅需要獲取圖像矩陣的begin和end,然后增加迭代從begin到end。將(*it)帶星操作符添加到迭代指針前,即可訪(fǎng)問(wèn)當(dāng)前指向的內(nèi)容。相比指針直接訪(fǎng)問(wèn)可能出現(xiàn)越界的問(wèn)題,迭代器絕對(duì)是非常安全的方法。
//顏色空間縮減
void colorReduceIterator(Mat& matInput,Mat& matoutput,int div){
//復(fù)制輸入圖像
matoutput=matInput.clone();
//初始位置迭代器
Mat_<Vec3b>::iterator it=matoutput.begin<Vec3b>();
//終止位置的迭代器
Mat_<Vec3b>::iterator itend =matoutput.end<Vec3b>();
//遍歷圖像矩陣
for (;it!=itend;++it) {
//處理每一個(gè)像素
(*it)[0]=(*it)[0]/div*div+div/2;
(*it)[1]=(*it)[1]/div*div+div/2;
(*it)[2]=(*it)[2]/div*div+div/2;
}
}動(dòng)態(tài)地址計(jì)算:
使用動(dòng)態(tài)地址來(lái)計(jì)算操作像素,需配合at方法的colorReduce 函數(shù)。這種方法簡(jiǎn)潔明了。但不是最快。
//顏色空間縮減
void colorReduceVec(Mat& matInput,Mat& matoutput,int div){
//參數(shù)準(zhǔn)備
matoutput=matInput.clone();
int rows=matoutput.rows;//行數(shù)
int cols=matoutput.cols;//列數(shù)
for (int i=0; i<rows; i++) {
for (int j=0; j<cols; j++) {//處理每一個(gè)像素
//藍(lán)色通道
matoutput.at<Vec3b>(i,j)[0]=matoutput.at<Vec3b>(i,j)[0]/div*div+div/2;
//綠色通道
matoutput.at<Vec3b>(i,j)[1]=matoutput.at<Vec3b>(i,j)[1]/div*div+div/2;
//紅色通道
matoutput.at<Vec3b>(i,j)[2]=matoutput.at<Vec3b>(i,j)[2]/div*div+div/2;
}
}
}at<Vec3b>(i,j)函數(shù)可以用來(lái)存取圖像元素,但是在編譯期必須知道圖像的數(shù)據(jù)類(lèi)型。務(wù)必保證指定的數(shù)據(jù)類(lèi)型和矩陣中的數(shù)據(jù)類(lèi)型相符合,因at方法本身不對(duì)任何數(shù)據(jù)類(lèi)型進(jìn)行轉(zhuǎn)換。
彩色圖像
每個(gè)像素由三個(gè)部分構(gòu)成,藍(lán)色通道、綠色通道、紅色通道 【BGR】 。
若帶Alpha通道,則每個(gè)像素由三個(gè)部分構(gòu)成,藍(lán)色通道、綠色通道、紅色通道 Alpha通道【BGRA】 。
三通道圖像
是指具有RGB三種通道的圖像,簡(jiǎn)單來(lái)說(shuō)就是彩色圖像。R:紅色,G:綠色,B:藍(lán)色。比如紅色為(255,0,0)
四通道圖像
是在三通道的基礎(chǔ)上加上了一個(gè)Alpha通道,Alpha用來(lái)衡量一個(gè)像素或圖像的透明度。比如Alpha為0時(shí),該像素完全透明,Alpha為255時(shí),該像素是完全不透明。 一個(gè)包含彩色圖像的Mat,會(huì)返回一個(gè)由3個(gè)8位數(shù)組成的向量。OpenCV中將此類(lèi)型的向量定義為Vec3b,即由3個(gè)unsigned char 組成的向量。若帶有alpha通道,則會(huì)返回一個(gè)由4個(gè)8位數(shù)組成的向量,OpenCV中將此類(lèi)型的向量定義為為Vec4b。所以我們可以這樣使用:matoutput.at<Vec3b>(i,j)[0]索引值0標(biāo)明了顏色的通道號(hào)為0。代表該點(diǎn)的B分量(藍(lán)色)。
圖像置灰
//置灰
-(UIImage *)grayInPutImage:(UIImage *)inputImage{
cv::Mat matInput=[[CVUtil sharedInstance]cvMatFromUIImage:inputImage];
cv:: Mat grayMat;
cv::cvtColor(matInput, grayMat,cv::COLOR_BGR2GRAY);
UIImage *imag=[[CVUtil sharedInstance]UIImageFromCVMat:grayMat];
return imag;
}方框?yàn)V波
//方框?yàn)V波操作
-(UIImage *)boxFilterInPutImage:(UIImage *)inputImage value:(int)value{
Mat matInput=[[CVUtil sharedInstance]cvMatFromUIImage:inputImage];
Mat boxFilterMat;
boxFilter(matInput, boxFilterMat, -1,cv::Size(value+1,value+1));
UIImage *imag=[[CVUtil sharedInstance]UIImageFromCVMat:boxFilterMat];
return imag;
}均值濾波
//均值濾波操作
-(UIImage *)blurInPutImage:(UIImage *)inputImage value:(int)value{
Mat matInput=[[CVUtil sharedInstance]cvMatFromUIImage:inputImage];
Mat blurMat;
blur(matInput, blurMat, cv::Size(value+1,value+1),cv::Point(-1,-1));
UIImage *imag=[[CVUtil sharedInstance]UIImageFromCVMat:blurMat];
return imag;
}高斯濾波
//高斯濾波操作
-(UIImage *)gaussianBlurInPutImage:(UIImage *)inputImage value:(int)value{
Mat matInput=[[CVUtil sharedInstance]cvMatFromUIImage:inputImage];
Mat gaussianBlurMat;
GaussianBlur(matInput, gaussianBlurMat, cv::Size(value*2+1,value*2+1), 0,0);
UIImage *imag=[[CVUtil sharedInstance]UIImageFromCVMat:gaussianBlurMat];
return imag;
}中值濾波
//中值濾波操作
-(UIImage *)medianBlurInPutImage:(UIImage *)inputImage value:(int)value{
Mat matInput=[[CVUtil sharedInstance]cvMatFromUIImage:inputImage];
Mat medianBlurMat;
medianBlur(matInput, medianBlurMat,value*2+1);
UIImage *imag=[[CVUtil sharedInstance]UIImageFromCVMat:medianBlurMat];
return imag;
}雙邊濾波
//雙邊濾波操作
-(UIImage *)bilateralFilterInPutImage:(UIImage *)inputImage value:(int)value{
Mat matInput=[[CVUtil sharedInstance]cvMatFromUIImage:inputImage];
Mat bilateralFilterMat;
Mat grayMat;
cvtColor(matInput, grayMat,cv::COLOR_BGR2GRAY);
bilateralFilter(grayMat, bilateralFilterMat, value, (double)value*2, (double)value/2);
UIImage *imag=[[CVUtil sharedInstance]UIImageFromCVMat:bilateralFilterMat];
return imag;
}腐蝕
//腐蝕操作
- (UIImage *)erodeInPutImage:(UIImage *)inputImage value:(int)value{
Mat matInput=[[CVUtil sharedInstance]cvMatFromUIImage:inputImage];
Mat element;
element=cv::getStructuringElement(MORPH_RECT, cv::Size(2*value+1,2*value+1),cv::Point(value,value));
Mat desimg;
erode(matInput,desimg,element);
UIImage *imag=[[CVUtil sharedInstance]UIImageFromCVMat:desimg];
return imag;
}膨脹
//膨脹操作
- (UIImage *)dilateInPutImage:(UIImage *)inputImage value:(int)value{
Mat matInput=[[CVUtil sharedInstance]cvMatFromUIImage:inputImage];
Mat element;
element=cv::getStructuringElement(MORPH_RECT, cv::Size(2*value+1,2*value+1),cv::Point(value,value));
Mat desimg;
dilate(matInput,desimg,element);
UIImage *imag=[[CVUtil sharedInstance]UIImageFromCVMat:desimg];
return imag;
}邊緣檢測(cè)
//邊緣檢測(cè)
-(UIImage *)cannyInPutImage:(UIImage *)inputImage value:(int)value{
if (value==0) {
return inputImage;
}
Mat srcImage=[[CVUtil sharedInstance]cvMatFromUIImage:inputImage];
Mat destImage;
destImage.create(srcImage.size(), srcImage.type());
Mat grayImage;
cvtColor(srcImage, grayImage, COLOR_BGR2GRAY);
Mat edge;
blur(grayImage,edge,cv::Size(value,value));
Canny(edge, edge, 13, 9 ,3);
destImage=Scalar::all(0);
srcImage.copyTo(destImage, edge);
UIImage *imag=[[CVUtil sharedInstance]UIImageFromCVMat:destImage];
return imag;
}圖像對(duì)比度和亮度調(diào)整
//調(diào)整對(duì)比度和亮度
-(UIImage *)contrasAndBrightInPutImage:(UIImage *)inputImage alpha:(NSInteger)alpha beta:(NSInteger)beta{
Mat g_srcImage=[[CVUtil sharedInstance]cvMatFromUIImage:inputImage];
if(g_srcImage.empty()){
return nil;
}
Mat g_dstImage=Mat::zeros(g_srcImage.size(),g_srcImage.type());
int height=g_srcImage.rows;
int width=g_srcImage.cols;
for (int row=0; row<height; row++) {
for (int col=0; col<width; col++) {
for (int c=0; c<4; c++) {//4通道BGRA圖像
g_dstImage.at<Vec4b>(row,col)[c]=saturate_cast<uchar>((alpha*0.01)*(g_srcImage.at<Vec4b>(row,col)[c])+beta);
}
}
}
UIImage *imag=[[CVUtil sharedInstance]UIImageFromCVMat:g_dstImage];
return imag;
}總結(jié)
OpenCV 的應(yīng)用領(lǐng)域非常廣泛,對(duì)于圖像處理、人機(jī)交互及機(jī)器學(xué)習(xí)算法感興趣的可以選擇一個(gè)方向進(jìn)行深入的研究。
到此這篇關(guān)于OpenCV- iOS 圖像處理編程入門(mén)的文章就介紹到這了,更多相關(guān)OpenCV iOS 圖像處理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
iOS實(shí)現(xiàn)封裝一個(gè)獲取通訊錄的工具類(lèi)詳解
這篇文章主要給大家介紹了關(guān)于iOS如何實(shí)現(xiàn)封裝一個(gè)獲取通訊錄的工具類(lèi)的相關(guān)資料,這是自己平時(shí)封裝的一個(gè)工具類(lèi),使用非常方便,文中給出了詳細(xì)的示例代碼,需要的朋友們可以參考借鑒,下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-10-10
深入學(xué)習(xí)iOS7自定義導(dǎo)航轉(zhuǎn)場(chǎng)動(dòng)畫(huà)
這篇文章主要為大家詳細(xì)介紹了iOS7自定義導(dǎo)航轉(zhuǎn)場(chǎng)動(dòng)畫(huà)的相關(guān)資料,感興趣的小伙伴們可以參考一下2016-02-02
IOS設(shè)計(jì)模式之組合設(shè)計(jì)模式
組合模式,Composite Pattern,是一個(gè)非常巧妙的模式。幾乎所有的面向?qū)ο笙到y(tǒng)都應(yīng)用到了組合模式,接下來(lái)通過(guò)本文給大家介紹IOS設(shè)計(jì)模式之組合設(shè)計(jì)模式,需要的朋友參考下2016-02-02
一行iOS代碼實(shí)現(xiàn)圖片無(wú)限輪播器
一行iOS代碼實(shí)現(xiàn)圖片無(wú)限輪播器的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05
Objective-C中block循環(huán)引用問(wèn)題詳解
這篇文章主要給大家介紹了關(guān)于Objective-C中block循環(huán)引用問(wèn)題的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Objective-C具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06
解決Xcode8打包上傳構(gòu)建版本無(wú)效的辦法
這篇文章主要介紹的是自己在打包上傳項(xiàng)目的時(shí)候遇到的一個(gè)問(wèn)題,通過(guò)自己的努力一步步解決了,現(xiàn)將解決方法方法分享給大家,希望給同樣遇到這個(gè)問(wèn)題的朋友們能有所幫助,下面來(lái)一起看看吧。2016-09-09
iOS touch事件區(qū)分單擊雙擊響應(yīng)的方法
如果您的 iPhone 應(yīng)用里有個(gè) view,既有單擊操作又有雙擊操作。用戶(hù)雙擊 view 時(shí),總是先執(zhí)行一遍單擊的操作再執(zhí)行雙擊的操作。所以直接判斷時(shí)就會(huì)發(fā)現(xiàn)不能直接進(jìn)入雙擊操作。下面是區(qū)分 touch 事件是單擊還是雙擊的方法,需要的朋友可以參考下2016-10-10

