欧美三级国产三级日韩三级_亚洲熟妇丰满大屁股熟妇_欧美亚洲成人一区二区三区_国产精品久久久久久模特

圖片高斯模糊處理應用 - 新聞資訊 - 云南小程序開發(fā)|云南軟件開發(fā)|云南網(wǎng)站建設-昆明葵宇信息科技有限公司

159-8711-8523

云南網(wǎng)建設/小程序開發(fā)/軟件開發(fā)

知識

不管是網(wǎng)站,軟件還是小程序,都要直接或間接能為您產(chǎn)生價值,我們在追求其視覺表現(xiàn)的同時,更側重于功能的便捷,營銷的便利,運營的高效,讓網(wǎng)站成為營銷工具,讓軟件能切實提升企業(yè)內部管理水平和效率。優(yōu)秀的程序為后期升級提供便捷的支持!

您當前位置>首頁 » 新聞資訊 » 技術分享 >

圖片高斯模糊處理應用

發(fā)表時間:2020-10-19

發(fā)布人:葵宇科技

瀏覽次數(shù):45


轉載請保存原文鏈接: http://write.blog.csdn.net/postedit/42400825
當今微博、同伙圈、各類社交平臺上充斥著各類照片,自拍或者各類生活記錄也多以照片為其重要的手段,可見照片對生活的重要性,所以圖片處理軟件幾乎成為人們的必備軟件之一。
因為人們對圖片處理的需求較大年夜,我欲望能開辟一款在生活中能應用的手機圖片處理軟件,于是我拔取了一個應用處景,即人們在各類場合拍┞氛時,只欲望照片顯示的重點是本身存眷的內容,而非其他事物,但照片不免包含其他不肯意讓別人看到的、可有可無的器械:比如小我隱私,路人等。
所以本應用軟件出生了,該應用軟件是一款運行于android體系上的應用軟件,其重要功能是讓用戶拔取一個可調節(jié)大年夜小的圓形區(qū)域,并模糊掉落圓形區(qū)域外的內容。

設計分析思路

拔取應用技巧:


Java是andorid應用軟件的重要開辟說話,應用java可以異常高效的開辟應用
NDK技巧:因為手機上的內存較少,處理器運算才能較弱,而應用Java對內存的┞菲握較弱,處理效力也不高,但圖片資本將占據(jù)較大年夜的內存空間,并且處理照片須要宏大年夜的運算,所以應用NDK技巧,一種基于JNI技巧(使得java可以或許調用其他說話所編寫的法度榜樣,如C/C++),并且包含很多處理對象的技巧。

關鍵技巧分析:


根據(jù)功能:1、解析圖片2、展示圖片3、拔取圓區(qū)域覆蓋的圖片,4、模糊圖片像素,
 1、不合格式的圖片,重要指的是圖片數(shù)據(jù)的存儲方法不合,該軟件今朝拔取的圖片格式為JPEG格式,應用LibJPEG開源庫解析和生成jpeg圖片
2、  展示圖片:
因為圖片大年夜小和比例和顯示區(qū)域大年夜小和比例難以完全像同,所認為了正常顯示圖片,并且節(jié)儉內存,應用插值法拔取圖片內容來顯示。
3、  拔取圓區(qū)域覆蓋的圖片:
設圓心為x0,y0,半徑為r,某一點的坐標為(x,y),則可得如下式子:
(x-x0)2+(y-y0)2 <= r2時, 該坐標為(x,y)是圓內的點
4、  模糊圖片像素
模糊的算法有很多,并且不合算法有特定的應用處合,根據(jù)應用功能:拔取了均值模糊和高斯模糊算法,均值模糊實現(xiàn)簡單,但模糊后的圖片持續(xù)性不強,顯示效不雅不好,所以拔取了高斯模糊算法
法度榜樣簡單流程圖
[img]http://img.blog.csdn.net/20150104212620782?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMDU5MzY4MA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast

各模塊(類)的功能及法度榜樣解釋;


選擇圖片部分,調用手機其他法度榜樣以獲取圖片路徑:
    Uri originalUri = data.getData();
                            String[] proj = {MediaStore.Images.Media.DATA };
                            // 似乎是android多媒體數(shù)據(jù)庫的封裝接口,具體的看Android文檔
                            Cursorcursor = managedQuery(originalUri, proj, null, null,
                                          null);
                            // 按我小我懂得 這個是獲得用戶選擇的圖片的索引值
                            int column_index =cursor
                                          .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                            // 將光標移至開首 ,這個很重要,不當心很輕易引起越界
                            cursor.moveToFirst();
                            // 最后根據(jù)索引值獲取圖片路徑
                            String path =cursor.getString(column_index);
經(jīng)由過程后綴名,初步斷定是否是JPEG圖片,如不雅后綴為.jpg則打開模糊設置界面:
if (path != null && path.endsWith(".jpg")) {
                                   ImageShare.imgPath= path;
                                   startActivity= CIRCLE_BLUZ;
                                   startActivity(intent);
                            } else {
                                   startActivity= 0;
                                   ToastUtil.show(this,"請選擇jpeg圖片");
                            }
本處所法:
//展示原始圖片,并獲取生成縮略圖
publicnative void showImg(Surface s, String imgPath);
//展示原圖縮略圖
       public native void showCurImg(Surface s);
//模糊原始圖片,并保存
       public native void circleBluz(StringsavePath, int x, int y, int radius,
                     float sigma);
//展示模糊效不雅,主如果處理縮略圖,并顯示
       public native void circleBluzShow(Surfaces, int x, int y, int radius,
                     float sigma);
//燒毀所有本地數(shù)據(jù)
       public native void destroyNativeAll();

關鍵模塊解釋


拔取圓形區(qū)域,為了進步效力進行了優(yōu)化
第一步:在圓的四周畫一個半徑為2r的┞俘方形,正方形的面積為4r2,
第二步:在圓內畫一個半徑為√ ̄2的┞俘方形,面積為2r2
第三步:斷定在第一步的┞俘方形中又不在第二步的┞俘方形中的像素是否在圓內
優(yōu)化效不雅為:削減了一半的像素(4r2,- 2r2)進行是否在圓內的斷定
      
int powr2 = r * r;
       //待檢區(qū)域
       int checkl, checkt, checkr, checkb;
       checkl = x0 - r > 0 ? x0 - r : 0;
       checkt = y0 - r > 0 ? y0 - r : 0;
       checkr = x0 + r >= width ? width : x0+ r;
       checkb = y0 + r >= height ? height :y0 + r;
 
       //免檢區(qū)域
       int notcl, notct, notcr, notcb;
       //sqrt(2)/2
       float sqrt2half = 0.7071;
       int nr = sqrt2half * r;
       notcl = x0 - nr > 0 ? x0 - nr : 0;
       notct = y0 - nr > 0 ? y0 - nr : 0;
       notcr = x0 + nr >= width ? width - 1 :x0 + nr;
       notcb = y0 + nr >= height ? height - 1: y0 + nr;
 
       int kcenter = ksize / 2;
       int i = 0, j = 0;
       unsigned long sum;
       //x偏向一維高斯模糊
       for (int y = 0; y < height; y++) {
              for (int x = 0; x < width; x++){
                     if (y >= checkt&& y <= checkb && x >= checkl && x <= checkr){
                            //斷定是否在免檢區(qū)域內
                            if (y >= notct&& y <= notcb && x >= notcl && x <= notcr) {
 
                            } else {
                                   //斷定是否在圓內
                                   if(pow2minus(y, y0) + pow2minus(x, x0) <= powr2) {
                                          //在圓內
                                   } else { //不在圓內
                                          //進行模糊處理,省略
                                   }
                            }
                     } else {//必定不在園內的像素
                            //進行模糊處理,省略
 
                                   }
                            }
                           
                     }
 
              }
       }
接下來的是最重要的模糊模塊:
模糊算法有很多 種,有最簡單的均值模糊,這種模糊對細節(jié)的保存不敷,圖片模糊后顯得很僵硬,不美不雅,不相符請求,就直接舍棄了,接下來選擇了高斯模糊,這種算法的思惟是離模糊中間像素越近的元素對該模糊后的像素影響越大年夜,所以應占據(jù)更大年夜的比重,越遠的像素占據(jù)的比重越小
請先瀏覽:http://blog.csdn.net/zddblog/article/details/7450033說得很具體
這里重要 應用了以上博客的算法,并作了優(yōu)化。用σ表示模糊程度,在大年夜概3σ距離之外的像素都可以看作不起感化,這些像素的計算也就可以忽視。平日,圖像處理法度榜樣只須要計算(6σ+1)*(6σ+1)的矩陣就可以包管相干像素影響。如下圖是σ=0.3時獲得的高斯模板矩陣,用這個矩陣來乘以中心像素四周的像素就可以獲得中心像素的實際值。(如計算模糊后的像素(i,j),則其值為(i-1,j-1)*1.47169e -005+(i-1,j)*0.00380683+....+(i+1,j+1)*1.47169e -005)
[img]http://img.blog.csdn.net/20150104215617812?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMDU5MzY4MA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast
高斯模糊第一步都是求高斯模糊的核心矩陣,接下來再用這個矩陣來計算每一個像素的實際值
//獲得高斯核矩陣 
void GaussianSmooth2D(double sigma, double ** & kernel, int& ksize) {

	//確保sigma為正數(shù)
	sigma = sigma > 0 ? sigma : 0;
	//高斯核矩陣的大年夜小為(6*sigma+1)*(6*sigma+1)
	ksize = ceil(sigma * 3) * 2 + 1;

	//計算高斯核矩陣
	//double *kernel = new double[ksize*ksize];
	kernel = (double **) malloc(sizeof(double*) * ksize);
	for (int i = 0; i < ksize; i++) {
		kernel[i] = (double *) malloc(sizeof(double) * ksize);
		memset(kernel[i], 0, ksize);
	}

	double scale = -0.5 / (sigma * sigma); //-1/2sigma的平方
	const double PI = 3.141592653;
	double cons = -scale / PI;

	double sum = 0.0;

	for (int i = 0; i < ksize; i++) {
		for (int j = 0; j < ksize; j++) {
			int x = i - (ksize - 1) / 2;
			int y = j - (ksize - 1) / 2;
			kernel[i][j] = cons * exp(scale * (x * x + y * y));

			sum += kernel[i][j];
		}
	}
	//歸一化
	for (int i = 0; i < ksize; i++) {
		for (int j = 0; j < ksize; j++) {
			kernel[i][j] /= sum;
		}
	}

}
接下來將膳綾擎兩處代數(shù)歸并應用,對圓外的像素進行模糊
//輸入兩個圖片模板的模糊函數(shù)
//圓型模糊圖片
int circleFuzzyDouble(unsigned char ** img, unsigned char ** imgtmp, int width,
		int height, int component, int x0, int y0, int r) {
	LOGI("circleFuzzy ");
	//高斯核矩陣
	double ** kernel;
	double sigma = 10.0;
	int ksize;
	GaussianSmooth2D(sigma, kernel, ksize);
	LOGI("獲得高斯矩陣  ");

	//3處理函數(shù)
	int powr2 = r * r;
	//待檢區(qū)域
	int checkl, checkt, checkr, checkb;
	checkl = x0 - r > 0 ? x0 - r : 0;
	checkt = y0 - r > 0 ? y0 - r : 0;
	checkr = x0 + r >= width ? width : x0 + r;
	checkb = y0 + r >= height ? height : y0 + r;

	//免檢區(qū)域
	int notcl, notct, notcr, notcb;
	//sqrt(2)/2
	float sqrt2half = 0.7071;
	int nr = sqrt2half * r;
	notcl = x0 - nr > 0 ? x0 - nr : 0;
	notct = y0 - nr > 0 ? y0 - nr : 0;
	notcr = x0 + nr >= width ? width - 1 : x0 + nr;
	notcb = y0 + nr >= height ? height - 1 : y0 + nr;

	//i控制行 紕謬邊沿進行處理
	for (int i = ksize; i < height - ksize; i++) {
		//j控制列 紕謬邊沿進行處理
		for (int j = ksize; j < width - ksize; j++) {
			//斷定是否在待檢查區(qū)域內
			if (i >= checkt && i <= checkb && j >= checkl && j <= checkr) {
				//斷定是否在免檢區(qū)域內
				if (i >= notct && i <= notcb && j >= notcl && j <= notcr) {

				} else {

					//斷定是否在圓內
					if (pow2minus(i, y0) + pow2minus(j, x0) <= powr2) {

					} else { //不在圓內 用高斯核矩陣進行模糊
						double middle[3] = { 0, 0, 0 };
						int mkl = j - ksize / 2;
						int mkt = i - ksize / 2;
						for (int k = 0; k < ksize; k++) {
							for (int l = 0; l < ksize; l++) {
								middle[0] += imgtmp[mkt + k][3 * (mkl + l)]
										* kernel[k][l];
								middle[1] += imgtmp[mkt + k][3 * (mkl + l) + 1]
										* kernel[k][l];
								middle[2] += imgtmp[mkt + k][3 * (mkl + l) + 2]
										* kernel[k][l];

							}
						}

						img[i][3 * j] = (unsigned char) middle[0];
						img[i][3 * j + 1] = (unsigned char) middle[1];
						img[i][3 * j + 2] = (unsigned char) middle[2];
					}
				}
			} else { //絕對不在圓內,對其進行模糊處理
				double middle[3] = { 0, 0, 0 };
				int mkl = j - ksize / 2;
				int mkt = i - ksize / 2;
				for (int k = 0; k < ksize; k++) {
					for (int l = 0; l < ksize; l++) {
						middle[0] += imgtmp[mkt + k][3 * (mkl + l)]
								* kernel[k][l];
						middle[1] += imgtmp[mkt + k][3 * (mkl + l) + 1]
								* kernel[k][l];
						middle[2] += imgtmp[mkt + k][3 * (mkl + l) + 2]
								* kernel[k][l];

					}
				}

				img[i][3 * j] = (unsigned char) middle[0];
				img[i][3 * j + 1] = (unsigned char) middle[1];
				img[i][3 * j + 2] = (unsigned char) middle[2];
			}
		}
	}
	LOGI("circleFuzzy end ");
	return 0;
}

以上代碼是沒有進行邊沿的像素處理的,可以把四周的像素也進行進行部分高斯核矩陣的乘法運算,但必定有部分矩陣的元素沒有對應的像素進行乘法,這時,必須對應用高斯模糊矩陣元素進行歸一化,不然元素明顯值變小,此處代碼大年夜家本身實現(xiàn)吧!
如許就能初步實現(xiàn)模糊的效不雅了,歇息一下!!看下實現(xiàn)的效不雅吧
[img]http://img.blog.csdn.net/20150104220951359?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMDU5MzY4MA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast
點擊√顯示效不雅
[img]http://img.blog.csdn.net/20150104220940121?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMDU5MzY4MA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast
然則膳綾擎的算法邊沿處理異常麻煩,運行耗時也異常大年夜,為了進一步晉升速度,可以將膳綾擎的二維高斯函數(shù),分別成兩次一維的高斯運算,一次對X偏向上,另一次對Y偏向上,膳綾擎的博客說得比較清跋扈了,進行這種變換,速度變?yōu)楸緛淼?倍以上,且不消受邊沿處理的懊末路。
	//浮點型的一維高斯核矩陣
<span style="white-space:pre">	</span>double * kdouble = (double *) malloc(sizeof(double) * ksize);

	double scale = -0.5 / (sigma * sigma);
	const double PI = 3.141592653;
	double cons = 1 / sqrt(-scale / PI);

	double sum = 0;
	int kcenter = ksize / 2;
	int i = 0, j = 0;
	for (i = 0; i < ksize; i++) {
		int x = i - kcenter;
		*(kdouble + i) = cons * exp(x * x * scale); //一維高斯函數(shù)
		sum += *(kdouble + i);

	}
	//歸一化,確保高斯權值袈溱[0,1]之間
	for (i = 0; i < ksize; i++) {
		*(kdouble + i) /= sum;
	}

接下來,我們在推敲運行情況,我們的應用運行在手機上,手機的處理器進行浮點運算的才能很弱,特別是該算法多次應用了double型變量,并且每個圓外像素均須要次數(shù)較大年夜的浮點運算,如不雅我們能將浮點運算轉化為整形運算,那么速度將大年夜幅晉升,而這是可以做到,并且比較簡單:可以用先把double型的kernel放大年夜必定倍數(shù),并保存為unsigned long型,今后就和本來運算一般,最后將求得的結不雅在縮小必定倍數(shù)即可。
//獲得一維unsigned long高斯 ,放大年夜0xffffff
void GaussianKerneluLong(unsigned long * & kernel, int sigma, int& ksize) {
	sigma = sigma > 0 ? sigma : -sigma;
	//高斯核矩陣的大年夜小為(6*sigma+1)*(6*sigma+1)
	//ksize為奇數(shù)
	unsigned long ratio = 0xffffff;
	ksize = ceil(sigma * 3) * 2 + 1;

	//浮點型的一維高斯核矩陣
	double * kdouble = (double *) malloc(sizeof(double) * ksize);

	//計算一維高斯核
	kernel = (unsigned long *) malloc(sizeof(unsigned long) * ksize);

	double scale = -0.5 / (sigma * sigma);
	const double PI = 3.141592653;
	double cons = 1 / sqrt(-scale / PI);

	double sum = 0;
	int kcenter = ksize / 2;
	int i = 0, j = 0;
	for (i = 0; i < ksize; i++) {
		int x = i - kcenter;
		*(kdouble + i) = cons * exp(x * x * scale); //一維高斯函數(shù)
		sum += *(kdouble + i);

	}
	//歸一化,確保高斯權值袈溱[0,1]之間
	for (i = 0; i < ksize; i++) {
		*(kdouble + i) /= sum;
	}

	//將double型矩陣轉化為long型(放大年夜ratio倍)
	for (i = 0; i < ksize; i++) {
		kernel[i] = kdouble[i] * ratio;
	}

	//釋放double型核矩陣
	free(kdouble);
}
如斯一來,優(yōu)化效不雅明顯,速度晉升為本來的8~9倍
接下來持續(xù)優(yōu)化的偏向是應用Neon和多線程
應用多線程優(yōu)化,可以將待模糊矩陣,分為手機處理器的核數(shù)個面積相等的矩陣,在進行模糊處理,速度可以或許晉升約等于核心數(shù)倍
該部分優(yōu)化將在后續(xù)更新,也迎接大年夜家給出更好的看法~ ~
感激大年夜家抽空看完這邊博客,如不雅認為對您有一些贊助,或者有一些疑問,可以鄙人方留言,迎接大年夜家交換評論辯論。
應用的apk文件在這里,源代碼在這里,建議先安裝apk試用功能。

相關案例查看更多