Dùng bộ lọc Gaussian để làm mờ ảnh

Bộ lọc Gaussian (Gaussian filter) là một công cụ phổ biến trong xử lý ảnh và tín hiệu, dùng chủ yếu để làm mờ (blur) hoặc giảm nhiễu trong ảnh hoặc tín hiệu đầu vào. Nó hoạt động bằng cách lấy trung bình có trọng số của các điểm ảnh lân cận, với trọng số được xác định theo phân phối Gaussian.

Hôm nay, mình sẽ hướng dẫn mọi người cách dùng bộ lọc Gaussian để làm mờ ảnh dùng ngôn ngữ Java với Android Studio.

Bước 1: Tải xuống hình ảnh và dán vào thư mục “res/drawable“:


Bước 2: Xây dựng giao diện trong tệp “activity_main.layout“:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<ImageView
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/img2"
android:layout_margin="10dp"
android:id="@+id/img1"
android:scaleType="fitCenter"
/>
<ImageView
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="@id/img1"
app:layout_constraintBottom_toTopOf="@id/btn_Gaussian"
android:layout_margin="10dp"
android:id="@+id/img2"
android:scaleType="fitCenter"
/>
<androidx.appcompat.widget.AppCompatButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Gaussian"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_margin="10dp"
android:background="#37FF00"
android:id="@+id/btn_Gaussian"
/>
</androidx.constraintlayout.widget.ConstraintLayout>

Bước 3: Viết chương trình trong tệp “MainActivity.java“:

package com.simpystore.myapplication;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.AppCompatButton;

public class MainActivity extends AppCompatActivity {

private ImageView img1;
private ImageView img2;
private AppCompatButton btn_Gaussian;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
img1 = findViewById(R.id.img1);
img2 = findViewById(R.id.img2);
btn_Gaussian = findViewById(R.id.btn_Gaussian);
Bitmap icon = BitmapFactory.decodeResource(getResources(),
R.drawable.picture);
img1.setImageBitmap(icon);

btn_Gaussian.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "Đang làm mờ", Toast.LENGTH_SHORT).show();
new Thread() {
public void run() {
Bitmap icon_Gaussian = blur(icon,5);
runOnUiThread(new Runnable() {
@Override
public void run() {
img2.setImageBitmap(icon_Gaussian);
}
});
}
}.start();
}
});

}

// Hàm tính giá trị Gaussian
private static float gaussian(int x, int y, float sigma) {
return (float) ((float) Math.exp(-(x * x + y * y) / (2 * sigma * sigma)) / (2 * Math.PI * sigma * sigma));
}

// Hàm làm mờ ảnh bằng thuật toán Gaussian Blur
public static Bitmap blur(Bitmap originalBitmap, float sigma) {
int width = originalBitmap.getWidth();
int height = originalBitmap.getHeight();
Bitmap blurredBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);

int[] pixels = new int[width * height];
originalBitmap.getPixels(pixels, 0, width, 0, 0, width, height);

// Tạo ma trận Gaussian
int radius = (int) (sigma * 3); // Chọn radius tương ứng với sigma
int size = radius * 2 + 1;
float[] gaussianKernel = new float[size * size];

// Tính toán ma trận Gaussian
for (int i = -radius; i <= radius; i++) {
for (int j = -radius; j <= radius; j++) {
gaussianKernel[(i + radius) * size + (j + radius)] = gaussian(i, j, sigma);
}
}

// Làm chuẩn hóa ma trận Gaussian
float kernelSum = 0;
for (int i = 0; i < gaussianKernel.length; i++) {
kernelSum += gaussianKernel[i];
}
for (int i = 0; i < gaussianKernel.length; i++) {
gaussianKernel[i] /= kernelSum;
}

// Áp dụng bộ lọc Gaussian Blur cho từng pixel
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
float red = 0, green = 0, blue = 0, alpha = 0;

// Áp dụng ma trận Gaussian cho vùng xung quanh pixel (x, y)
for (int ky = -radius; ky <= radius; ky++) {
for (int kx = -radius; kx <= radius; kx++) {
int px = Math.min(width - 1, Math.max(0, x + kx));
int py = Math.min(height - 1, Math.max(0, y + ky));
int color = pixels[py * width + px];

// Lấy các thành phần màu của pixel
int r = Color.red(color);
int g = Color.green(color);
int b = Color.blue(color);
int a = Color.alpha(color);

// Áp dụng trọng số Gaussian
float weight = gaussianKernel[(ky + radius) * size + (kx + radius)];

red += r * weight;
green += g * weight;
blue += b * weight;
alpha += a * weight;
}
}

// Gán giá trị pixel đã làm mờ
int newColor = Color.argb((int) alpha, (int) red, (int) green, (int) blue);
blurredBitmap.setPixel(x, y, newColor);
}
}

return blurredBitmap;
}

}

Kết quả:


Liên kết Youtube hướng dẫn:





Comments