圖片馬賽克原理下圖所示:
圖片是由一個個像素組成,每個紅框表示一個像素,每一個像素都有一個RGBA的值,這里隨便用一寫字母表示其顏色值。
這里拿馬賽克大小為3個像素寬度舉例,如果設(shè)置為3個像素寬度的馬賽克處理,則每次手機(jī)會處理3*3共9個像素的矩陣,將這9個像素值處理成與矩陣第一個像素的值相等的像素值,然后重新填充矩陣像素值。每次從左到右,從上到下,以步長為3個像素,去處理每個3*3的像素矩陣,將這9個像素值處理成與矩陣第一個像素的值相等的像素值,直到將整個圖片的像素處理完成,生成馬賽克圖片。
下圖為原圖與處理后生成的二維碼圖片
上代碼:
創(chuàng)建一個ImageUtils類,提供一個將原圖轉(zhuǎn)換成馬賽克圖片的方法
ImageUtils.h的代碼如下,需要導(dǎo)入OpenCV的一些文件,
#import <UIKit/UIKit.h>
//導(dǎo)入OpenCV框架
//核心頭文件
#import <opencv2/opencv.hpp>
//對ios支持
#import <opencv2/imgcodecs/ios.h>
//導(dǎo)入矩陣幫助類
#import <opencv2/highgui.hpp>
#import <opencv2/core/types.hpp>
//導(dǎo)入C++命名空間
using namespace cv;
@interface ImageUtils:NSObject
//定義方法:處理圖片
+(UIImage*)opencvImage:(UIImage*)image level:(int)level;
@end
因?yàn)橛玫搅薈++,所以ImageUtils.m也要改成ImageUtils.mm,ImageUtils.mm的實(shí)現(xiàn)如下
#import "ImageUtils.h"
@implementation ImageUtils
+(UIImage*)opencvImage:(UIImage*)image level:(int)level{
? ? ? //實(shí)現(xiàn)功能? ?
? ? ? //第一步:將iOS圖片->OpenCV圖片(Mat矩陣)? ??
? ? ? Mat mat_image_src;? ??
? ? ? UIImageToMat(image, mat_image_src);? ? ? ??
? ? ? //第二步:確定寬高? ??
? ? ? int width = mat_image_src.cols;? ??
? ? ? int height = mat_image_src.rows;? ? ? ??
? ? ? //圖片類型->進(jìn)行轉(zhuǎn)換? ??
? ? ? //在OpenCV里面? ??
? ? ? //坑隱藏? ??
? ? ? //支持->RGB處理? ??
? ? ? //圖片ARGB? ??
? ? ? //將ARGB->RGB? ??
? ? ? Mat mat_image_dst;? ??
? ? ? //一定要記得轉(zhuǎn)換類型
? ? ? cvtColor(mat_image_src, mat_image_dst, CV_RGBA2RGB, 3);? ? ? ??
? ? ? //為了不影響原始圖片? ??
? ? ? Mat mat_image_clone = mat_image_dst.clone();? ? ? ??
? ? ? ?//第三步:馬賽克處理? ?
? ? ? ?//分析馬賽克算法原理? ??
? ? ? ?//level = 3-> 3 * 3矩形? ??
? ? ? ?//動態(tài)的處理? ??
? ? ? ?int x = width - level;? ?
? ? ? ?int y = height - level;? ? ? ??
? ? ? ?for (int i = 0; i < y; i += level) {? ? ? ??
? ? ? ? ? ? ?for (int j = 0; j < x; j += level) {? ? ? ? ? ??
? ? ? ? ? ? ? ? ?//創(chuàng)建一個矩形區(qū)域? ? ? ? ? ?
? ? ? ? ? ? ? ? ?Rect2i mosaicRect = Rect2i(j, i, level, level);? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? ?//給填Rect2i區(qū)域->填充數(shù)據(jù)->原始數(shù)據(jù)? ? ? ? ? ??
? ? ? ? ? ? ? ? ?Mat roi = mat_image_dst(mosaicRect);? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? ?//讓整個矩形區(qū)域顏色值保持一致? ? ? ? ? ??
? ? ? ? ? ? ? ? ?//mat_image_clone.at(i, j)->像素點(diǎn)(顏色值組成->多個)->ARGB->數(shù)組? ? ? ? ? ??
? ? ? ? ? ? ? ? ?//mat_image_clone.at(i, j)[0]->R值? ? ? ? ? ??
? ? ? ? ? ? ? ? ?//mat_image_clone.at(i, j)[1]->G值? ? ? ? ? ?
? ? ? ? ? ? ? ? ?//mat_image_clone.at(i, j)[2]->B值? ? ? ? ? ?
? ? ? ? ? ? ? ? Scalar scalar = Scalar( ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?mat_image_clone.at(i, j)[0],? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?mat_image_clone.at(i, j)[1],? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? mat_image_clone.at(i, j)[2]);
? ? ? ? ? ? ? ? ?//將處理好矩形區(qū)域->數(shù)據(jù)->拷貝到圖片上面去->修改后的數(shù)據(jù)
? ? ? ? ? ? ? ? ?//CV_8UC3解釋一下->后面也會講到
? ? ? ? ? ? ? ? ?//CV_:表示框架命名空間
? ? ? ? ? ? ? ? ?//8表示:32位色->ARGB->8位 = 1字節(jié) -> 4個字節(jié)
? ? ? ? ? ? ? ? ?//U分析
? ? ? ? ? ? ? ? ?//兩種類型:有符號類型(Sign->有正負(fù)->簡寫"S")、無符號類型(Unsign->正數(shù)->"U")
? ? ? ? ? ? ? ? ?//無符號類型:0-255(通常情況)
? ? ? ? ? ? ? ? ?//有符號類型:-128-127
? ? ? ? ? ? ? ? ?//C分析:char類型
? ? ? ? ? ? ? ? ?//3表示:3個通道->RGB
? ? ? ? ? ? ? ? ?Mat roiCopy = Mat(mosaicRect.size(), CV_8UC3, scalar);
? ? ? ? ? ? ? ? ?roiCopy.copyTo(roi);
? ? ? ? ? }
? ? ?}
? ? //第四步:將OpenCV圖片->iOS圖片
? ? return MatToUIImage(mat_image_dst);
}
@end
調(diào)用ImageUtils相應(yīng)的代碼:
#import "ImageUtils.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@end
@implementation ViewController
- (void)viewDidLoad {
? ? ? ? [super viewDidLoad];
}
//正常圖片
- (IBAction)clickNormal:(id)sender {
? ? ? ? _imageView.image = [UIImage imageNamed:@"girl.jpeg"];
}
//馬賽克圖片
- (IBAction)clickMosaic:(id)sender {
? ? ? ? _imageView.image = [ImageUtils opencvImage:_imageView.image level:20];
}
@end