Reprint please keep the original link: http://write.blog.csdn.net/postedit/42400825

Today's microblog, circle of friends, all kinds of social platforms are filled with photos, selfies or a variety of life records also take photos as their main means, visible photos of the importance of life, so the image processing software almost become one of the necessary software.

Because people have a large demand for picture processing, I hope to develop a mobile phone image processing software that can be used in life, so I chose an application scenario, that is, people in various occasions to take photos, only want to show the focus of their own attention to the content, rather than other things, but the photo will inevitably contain other people do not want to see, Unimportant things: such as personal privacy, passers-by, etc.

So the application software was born, the application software is running on the Android system application software, its main function is to allow the user to select an adjustable size of the circular area, and blur out of the circle outside the area of the content.

Design analysis Ideas to choose the use of technology:

Java is the main development language for Andorid applications, and Java can be used to develop applications very efficiently.

NDK technology: Due to the low memory on the phone, the processor is weak, and the use of Java for memory control is weak, processing efficiency is not high, but the picture resources will occupy a large amount of memory space, and processing photos require a large operation, so using NDK technology, a JNI-based technology ( Enables Java to invoke programs written in other languages, such as C + +, and contains many techniques for processing tools.

Key Technical Analysis:

According to the function: 1, the resolution Picture 2, the display Picture 3, selects the Circle area overlay picture, 4, the blurred picture pixel,

1, the different format of the picture, mainly refers to the picture data storage method is different, the software currently selected image format for JPEG format, using Libjpeg Open Source Library to parse and generate JPEG images

2, display pictures:

Because the picture size and scale and display area size and proportions are difficult to completely resemble, so in order to display the picture normally, and save memory, using the interpolation method to select the picture content to display.

3. Select the image covered by the Circle area:

Set the center point to x0,y0, the radius is r, and the coordinates of the bit are (x, y), you can get the following formula:

(x-x0) (Y-Y0) 2 <= R2, the coordinate is (x, y) is the point within the circle

4. Blurred picture pixels

There are many fuzzy algorithms, and different algorithms have specific applications, according to the application function: The mean fuzzy and Gaussian fuzzy algorithm is selected, the mean value fuzzy realization is simple, but the image continuity is not strong, the display effect is not good, so the Gaussian fuzzy algorithm is selected

Program Brief flowchart

The function and program description of each module (class);

Select the picture section and call other programs on your phone to get the picture path:

Uri Originaluri = Data.getdata ();

String[] proj = {MediaStore.Images.Media.DATA};

It seems to be an interface for Android multimedia database, specifically look at the Android document

Cursorcursor = Managedquery (Originaluri, proj, NULL, NULL,

NULL);

As I understand it, this is the index value of the image that the user chooses.

int Column_index =cursor

. Getcolumnindexorthrow (MediaStore.Images.Media.DATA);

Move the cursor to the beginning, this is important, careless can easily cause a cross-border

Cursor.movetofirst ();

Finally get the picture path according to the index value

String path =cursor.getstring (column_index);

With the suffix name, the initial judgment is whether the JPEG picture, if the suffix is. jpg, opens the Blur Settings screen:

if (path! = null && path.endswith (". jpg")) {

Imageshare.imgpath= path;

Startactivity= Circle_bluz;

StartActivity (Intent);

} else {

startactivity= 0;

Toastutil.show (This, "Please select JPEG image");

}

Local method:

Show the original picture and get the generated thumbnail

publicnative void Showimg (Surface s, String Imgpath);

Display the original thumbnail image

public native void Showcurimg (Surface s);

Blur the original picture and save

public native void Circlebluz (stringsavepath, int x, int y, int radius,

float sigma);

Shows the blur effect, mainly dealing with thumbnails, and showing

public native void Circlebluzshow (surfaces, int x, int y, int radius,

float sigma);

Destroy all local data

public native void Destroynativeall ();

Key module Description

Selection of circular areas, optimized for improved efficiency

The first step: Draw a square with a radius of 2r around the circle, the square area is 4R2,

Step two: Draw a square with a radius of √￣2 in the circle, with an area of 2r2

Step three : determine if the pixels in the square in the first step are not in the second step are inside the circle

the optimization effect is : reduce the pixel by half (4r2,- 2r2) whether to make judgments within the circle

int POWR2 = R * r; Pending area 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; Exempt area 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 direction a Gaussian blur for (int y = 0, y < height; y++) {for (int x = 0; x < width, x + +) { if (y >= checkt&& y <= checkb && x >= checkl && x <= checkr) { Determine if in the exemption area if (Y >= notct&&amP Y <= notcb && x >= notcl && x <= NOTCR) {} else { Determine if within the circle if (Pow2minus (y, y0) + pow2minus (x, x0) <= powr2) { Inside the circle} else {//not within the circle Obfuscated, omitted}}} else {//must not be in the garden Pixel//Blur, omit}} } } }

The following are the most important fuzzy modules:

There are many kinds of fuzzy algorithms, there are the simplest mean fuzzy, this fuzzy to the details of the reservation is not enough, the image is very stiff after the blur, not in line with the requirements, directly discarded, the next choice of Gaussian Blur, the idea of the algorithm is the fuzzy center pixels closer to the blurred pixel effect of the greater, So should occupy a larger proportion, the farther the pixels occupy the smaller proportion

Please browse First: http://blog.csdn.net/zddblog/article/details/7450033 is very detailed.

Here the main use of the above blog algorithm, and optimized. Using σ to indicate the degree of ambiguity, pixels outside the approximate 3σ distance can be seen as not working, and the calculation of these pixels can be ignored. In general, the image processing program only needs to calculate (6σ+1) * (6σ+1) of the matrix to guarantee the relevant pixel influence. As the Gaussian template matrix obtained when σ=0.3, the actual value of the intermediate pixels can be obtained by multiplying the pixels around the intermediate pixels with this matrix. (for example, if the blurred Pixel (i,j) is calculated, its value is (i-1,j-1) *1.47169e-005+ (i-1,j) *0.00380683+....+ (i+1,j+1) *1.47169e-005)

Gaussian blur the first step is to find the core matrix of Gaussian blur, and then use this matrix to calculate the actual value of each pixel

Get Gaussian kernel matrix void gaussiansmooth2d (double sigma, double * * & kernel, int& ksize) {//ensure Sigma is positive sigma = sigma > 0? The size of the sigma:0;//Gaussian core matrix is (6*sigma+1) * (6*sigma+1) ksize = Ceil (Sigma * 3) * 2 + 1;//compute Gaussian kernel matrix//double *kernel = new Double[ksize*k Size];kernel = (double * *) malloc (sizeof (double*) * ksize); for (int i = 0; i < ksize; i++) {kernel[i] = (double *) Mall OC (sizeof (double) * ksize); memset (Kernel[i], 0, ksize);} Double scale = -0.5/(sigma * sigma); -1/2sigma Square 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 (SCA Le * (x * x + y * y)); sum + = Kernel[i][j];}} Normalized for (int i = 0, i < ksize; i++) {for (int j = 0; J < Ksize; J + +) {kernel[i][j]/= sum;}}

Next, combine the above two algebra to blur the pixels outside the circle

Input two image template blur function//round blur picture int circlefuzzydouble (unsigned char * * img, unsigned char * * imgtmp, int width,int height, int comp onent, int x0, int y0, int r) {logi ("Circlefuzzy");//Gaussian kernel matrix double * * kernel;double sigma = 10.0;int ksize; Gaussiansmooth2d (Sigma, kernel, ksize); Logi ("Get Gaussian Matrix");//3 handler int powr2 = R * r;//pending area 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;//exempt area int NOTCL, NOTCT, NOTCR, Notcb;//sqrt (2)/2float 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 control line does not handle edges for (int i = ksize; i < height-ksize; i++) {//j control column does not handle edges for (int j = ksize; j < width-ksize; J + +) {//Determine if within the area to be inspected if (I >= checkt && i <= checkb && J >= Checkl && J <= Checkr) {//Determine if within the exemption area if (I >= notct && i <= NOTCB && J >= Notcl && J < = NOTCR) {} else {//To determine whether within the circle if (Pow2minus (i, y0) + Pow2minus (j, x0) <= powr2) {} else {//not within the circle with a Gaussian kernel matrix for a fuzzy 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 {//never within a circle, obfuscate it with double middle[3] = {0, 0, 0};int mkl = j-ksize/2;int mkt = i-ksize/2;for (int k = 0; K & Lt Ksize; k++) {for (int l = 0; l < ksize; l++) {middle[0] + = Imgtmp[mkt + k][3 * (Mkl + L)]* kernel[k][l];middle[1] + = IMGTMP[MK T + 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;}

The above code is not the edge of the pixel processing, the surrounding pixels can also be used to perform a partial Gaussian kernel matrix multiplication, but there must be some elements of the matrix is not the corresponding pixel multiplication, at this time, the use of Gaussian fuzzy matrix elements should be normalized, otherwise the element is significantly smaller, the code here to achieve their own !

This will be able to achieve a preliminary fuzzy effect, rest!! Look at the effect of the implementation.

Click Yes to display the effect

But the above algorithm edge processing is very troublesome, running time is very large, in order to further improve the speed, can be the above Ivigos function, separated into two one-dimensional Gaussian operation, one to the x direction, the other on the y direction, the above blog said more clearly, to make this transformation, the speed of the original more than twice times, And not be bothered by edge processing.

A Gaussian core matrix of floating-point type <span style= "White-space:pre" ></span>double * kdouble = (double *) malloc (sizeof (double) * ksize);d ouble scale = -0.5/(Sigma * sigma), const double PI = 3.141592653;double cons = 1/sqrt (-scale/pi);d ouble sum = 0;int Kcenter = Ksize/2;int i = 0, j = 0;for (i = 0; i < ksize; i++) {int x = i-kcenter;* (kdouble + i) = cons * E XP (x * x * scale); A Gaussian function sum + = * (kdouble + i);} Normalization, ensuring that the Gaussian weights are between [0,1] for (i = 0; i < ksize; i++) {* (kdouble + i)/= sum;}

Next, we consider the operating environment, our application runs on the phone, the phone's processor is weak in floating-point operations, especially the algorithm uses double variable multiple times, and each outer pixel requires a large number of floating-point operations, if we can convert floating-point operations into shaping operations, Then the speed will be greatly improved, and this can be done, and relatively simple: you can use the double type of kernel to enlarge a certain multiple, and save as unsigned long, and then the original operation in general, the result will be obtained in the reduction of a certain multiple.

//get one-dimensional unsigned Long Gaussian, magnification 0xffffffvoid gaussiankernelulong (unsigned long * & kernel, int sigma, int& ksize) {sigma = sigma > 0 ? Sigma: The size of the-sigma;//Gaussian core matrix is (6*sigma+1) * (6*sigma+1)//ksize is odd unsigned long ratio = 0xffffff;ksize = Ceil (Sigma * 3) * 2 + 1; A Gaussian core matrix of floating-point type double * kdouble = (double *) malloc (sizeof (double) * ksize);//compute a Gaussian kernel kernel = (unsigned long *) malloc (Sizeo F (unsigned long) * ksize);d ouble scale = -0.5/(sigma * sigma); const double PI = 3.141592653;double cons = 1/sqrt (-scal E/PI);d ouble sum = 0;int Kcenter = Ksize/2;int i = 0, j = 0;for (i = 0; i < ksize; i++) {int x = i-kcenter;* (Kdou ble + i) = cons * EXP (x * x * scale); A Gaussian function sum + = * (kdouble + i);} Normalization, ensuring that the Gaussian weights are between [0,1] for (i = 0; i < ksize; i++) {* (kdouble + i)/= sum;} Converts a double matrix to a long (magnified ratio times) for (i = 0; i < ksize; i++) {kernel[i] = kdouble[i] * ratio;} Release of the double-core matrix free (kdouble);}

As a result, the optimization effect is obvious and the speed is increased to the original 8~9 times.

The next direction to continue optimization is to use neon and multithreading

Using multi-threaded optimization, the fuzzy matrix can be divided into the cell phone processor's core number of the same area of the matrix, in the process of fuzzy processing, the speed can be increased by approximately equal to the core number of times

This part of the optimization will be in the next update, but also welcome you to give better comments ~ ~

Thank you for the time to read this blog, if you feel some help, or have some questions, you can leave a message below, welcome to exchange discussions.

App apk file here, the source code is here, it is recommended to install the APK trial function first.

Image Gaussian blur application-involving the use of libjpeg, NDK operations on Surfaceview, image obfuscation, source code