OpenCV初體驗,給圖片打碼html
提到OpenCV,相信大多數人都據說過,應用領域很是普遍,使用C++開發,天生具備跨平臺的優點,咱們學習一次,就能夠在各個平臺使用,這個仍是很具備誘惑力的。
本文主要記錄我第一次使用OpenCV,在iOS開發平臺上面搭建開發環境,而且實現一個簡單的馬賽克功能
開發環境:Swift四、XCode 9.0ios
一、什麼是OpenCV?
* 由英特爾公司於1999年發起並參與開發,至今已有18年曆史
* OpenCV的全稱是Open Source Computer Vision Library
* 是一個跨平臺的開源計算機視覺庫,可用於開發實時的圖像處理、計算機視覺以及模式識別程序。
* 支持C/C++、Java、Python、OC、Swift、Ruby等等語言
* 支持Windows、 Android、 Maemo、 FreeBSD、 OpenBSD、 iOS、 Linux和Mac OSc++
二、難點,思路
* 因爲咱們使用的是Swift,因爲目前還不能在Swift中使用C++的類,因此咱們得想一個方法,在Swift中調用C++的類
* 其實方法很簡單,Swift天生具備跟Objective-C++混編的能力,而Objective-C++裏面是能夠直接使用C++的類的,上面的問題也就解決了。swift
三、馬賽克原理
* 其實把圖片的像素密度調低,就能夠出現馬賽克效果了
* 開始作馬賽克以前,須要定一個馬賽克的級別,表示原圖中每幾個像素變成新圖裏面的一個像素
* 取一小塊區域左上角的一個像素,並把這個像素填充到整個小區域內
* 以下圖,左邊是原圖,右邊是通過變換以後的圖,假設馬賽克級別爲3,每一個數字表示的區域就是處理的一個小單元,取這個最小單元左上角的顏色,填充整個小單元就OK了vim
四、開動工程
4.一、搭建c++和swift混編環境
咱們首先要搭建一個c++的環境,而後才能進行c++的開發,而c++環境能夠經過iostream裏面的cout函數驗證
1.首先,咱們使用xCode新建一個swift的iOS項目
2.在工程內,新建一個Objective-C類,繼承NSObject,這裏會自動提示咱們是否爲項目添加橋接文件,選擇添加便可(橋接文件是用來向Swift暴露Objective-C方法的)
3.由於咱們要使用Objective-C++,而把Objective-C轉成Objective-C++的方法有兩種
* 把.m文件的後綴名改成.mm,xCode就會自動識別咱們的代碼爲Objective-C++了(xCode會經過後綴名自動識別源文件類型)
* 選中要修改的.m文件,在右邊的Type屬性修改爲:Objective-C++ Source(也能夠手動指定源文件類型)數組
4.在剛纔的.mm文件中,添加一個測試方法,在這裏測試一下C++環境是否搭建成功框架
1 #import "MyUtil.h" 2 #import <iostream> 3 using namespace std; 4 @implementation MyUtil 5 + (void)testCpp { 6 cout << "Hello Swift and Cpp" << endl; 7 }
5.在前面xCode自動建立的橋接文件中暴漏咱們的測試方法頭文件ide
6.在Swift中調用測試方法,控制檯輸出 "Hello Swift and Cpp" 就正常了函數
4.二、導入OpenCV動態庫學習
在iOS開發中導入OpenCV的庫很簡單,去官網下載咱們須要的framework拖拽到工程文件或者用cocopods導下載便可
4.三、實現馬賽克函數
下面進入正題
1.首先在.mm文件中 ,導入OpenCV的頭文件,導入頭文件以後代碼以下,這裏有幾個坑要注意:
不要在.h文件中去導入OpenCV的相關頭文件,不然會報錯,錯誤信息: Core.hpp header must be compiled as C++,看到這個問題,趕忙把頭文件移動到.m文件中去
還有就是OpenCV的頭文件最好放在#import以前,不然也會報一個錯誤: enum { NO, FEATHER, MULTI_BAND }; Expected identifier
1 // 倒入OpenCV框架 最好放在Foundation.h UIKit.h以前 2 // 核心頭文件 3 #import <opencv2/opencv.hpp> 4 // 對iOS支持 5 #import <opencv2/imgcodecs/ios.h> 6 // 倒入矩陣幫助類 7 #import <opencv2/highgui.hpp> 8 #import <opencv2/core/types.hpp> 9 10 #import "MyUntil.h" 11 #import <iostream> 12 using namespace std; 13 using namespace cv;
2.實現馬賽克函數
1 +(UIImage *)opencvimage:(UIImage *)image level:(int)level{ 2 // 實現功能 3 // 第一步:將iOS圖片->OpenCV圖片(Mat矩陣) 4 Mat mat_image_src; 5 UIImageToMat(image, mat_image_src); 6 7 // 第二步:肯定高度 8 int width = mat_image_src.cols; 9 int height = mat_image_src.rows; 10 11 // 在OpenCV裏面,必需要先把ARGB的顏色空間轉換成RGB,不然處理會失敗 12 // ARGB->RGB 13 Mat mat_image_dst; 14 cvtColor(mat_image_src, mat_image_dst, CV_RGBA2BGR, 3); 15 // 爲了避免影響原始圖片,克隆一張保存 16 Mat mat_image_clone = mat_image_dst.clone(); 17 18 //第三步:馬賽克處理 19 int xMax = width - level; 20 int yMax = height - level; 21 for (int y = 0; y <= yMax; y += level) { 22 for (int x = 0; x <= xMax; x += level) { 23 // 讓整個巨型區域顏色值保持一致 24 // mat_image_clone.at<Vec3d>(i, j)->像素點(顏色值組成->多個)->ARGB->數組 25 // mat_image_clone.at<Vec3d>(i, j)[0]->R值 26 // mat_image_clone.at<Vec3d>(i, j)[1]->G值 27 // mat_image_clone.at<Vec3d>(i, j)[2]->B值 28 Scalar scalar = Scalar(mat_image_clone.at<Vec3b>(y, x)[0], 29 mat_image_clone.at<Vec3b>(y, x)[1], 30 mat_image_clone.at<Vec3b>(y, x)[2]); 31 //取出要處理的矩形區域 32 Rect2i mosaicRect = Rect2i(x, y, level, level); 33 Mat roi = mat_image_dst(mosaicRect); 34 35 //將前面處理的小區域拷貝到要處理的區域 36 //CV_8UC3的含義 37 //CV_:表示框架命名空間 38 //8表示:32位色->ARGB->8位 = 1字節 -> 4個字節 39 //U: 無符號類型 40 //C分析:char類型 41 //3表示:3個通道->RGB 42 Mat roiCopy = Mat(mosaicRect.size(), CV_8UC3, scalar); 43 roiCopy.copyTo(roi); 44 45 } 46 } 47 // 第四步:將OpenCV圖片->iOS圖片 48 return MatToUIImage(mat_image_dst); 49 }
4.四、在swift中調用馬賽克函數
函數已經實現了,接下來就是在Swift中調用了
1.爲了便於測試,咱們在storyboard中搭一個簡單的界面,在按鈕中切換馬賽克圖片和原圖,界面以下:
2.在按鈕點擊事件中調用上面的馬賽克函數便可
1 @IBAction func origImageAction(_ sender: UIButton) { 2 // 顯示原圖點擊事件 3 _imageView.image = UIImage.init(named: "bgview") 4 } 5 6 @IBAction func mosaicImageAction(_ sender: UIButton) { 7 // 打碼 8 /** 9 + (UIImage *)opencvimage:(UIImage *)image level:(int)level; 10 實現馬賽克功能函數 11 @param image 要處理的圖片 12 @param level 馬賽克等級,越大越模糊 13 @return 處理好的圖片 14 */ 15 _imageView.image = MyUntil.opencvimage(_imageView.image, level: 5) 16 }
3.效果以下
五、後記
對OpenCV的探索還將繼續,不斷積累,貴在點滴~