Swift與C++混編 OpenCV初體驗 圖片打碼~

OpenCV初體驗,給圖片打碼html

提到OpenCV,相信大多數人都據說過,應用領域很是普遍,使用C++開發,天生具備跨平臺的優點,咱們學習一次,就能夠在各個平臺使用,這個仍是很具備誘惑力的。
本文主要記錄我第一次使用OpenCV,在iOS開發平臺上面搭建開發環境,而且實現一個簡單的馬賽克功能
開發環境:Swift四、XCode 9.0
ios

 

一、什麼是OpenCV?
* 由英特爾公司於1999年發起並參與開發,至今已有18年曆史

* OpenCV的全稱是Open Source Computer Vision Library

* 是一個跨平臺的開源計算機視覺庫,可用於開發實時的圖像處理、計算機視覺以及模式識別程序。

* 支持C/C++、Java、Python、OC、Swift、Ruby等等語言

* 支持Windows、 Android、 Maemo、 FreeBSD、 OpenBSD、 iOS、 Linux和Mac OS
c++

 

二、難點,思路
* 因爲咱們使用的是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的探索還將繼續,不斷積累,貴在點滴~

相關文章
相關標籤/搜索