در این قسمت تیم کدگیت را با آموزش تبدیل کسینوسی گسسته در جاوا (DCT)همراهی کنید. ابتدای این جلسه طبق روال گذشته در مورد الگریتم DCT یا تبدیل کسینوسی گسسته توضیحی خواهیم داد و سپس به پیاده سازی این الگوریتم در زبان جاوا خواهیم پرداخت. همچنین پیش نیازهای این آموزش شامل موارد زیر میباشد:
تبدیل کسینوسی گسسته
یک تبدیل کسینوسی گسسته: دنبالهای محدود از نقاط داده را بهصورت مجموع توابع کسینوسی که در بسامدهای متفاوت نوسان میکنند، نمایش میدهد. این تبدیلها استفاده گستردهای در علم و مهندسی ایفا میکنند؛ از فشردهسازی با اتلاف دادههای صوتی مانند MP3 و تصاویر مانند JPEG (که تکههای کوچک با بسامدهای بالا قابل حذف هستند) تا روشهای طیفی برای راه حل عددی معادله دیفرانسیل با مشتقات پارهای در گسترهٔ استفادهٔ DCTها قرار میگیرد.
از آنجایی که توابع کسینوسی کمتری برای تقریب زدن یک سیگنال عادی مورد نیاز است (به نسبت توابع سینوسی)، استفاده از تابع کسینوس به جای سینوس در فشردهسازی ضروری است. همچنین بهنسبت توابع دیفرانسیل، توابع کسینوسی دارای شرایط مرزی مشخصتری هستند(ویکیپدیا).
الگوریتم تبدیل کسینوسی گسسته در جاوا
برای پیاده سازی تبدیل کسینوسی گسسته ابتدا باید با الگوریتم آن آشنا بود. الگوریتم این تبدیل به صورت زیر است:
dct[i][j] = ci * cj (sum(k=0 to m-1) sum(l=0 to n-1) matrix[k][l] * cos((2*k+1) *i*pi/2*m) * cos((2*l+1) *j*pi/2*n)
متغیرهای ci و cj از فرمول زیر بدست میآیند:
- اگر i=0 باشد(ci= 1/sqrt(m در غیر این صورت (ci= sqrt(2)/sqrt(m
- اگر i=0 باشد (cj= 1/sqrt(n در غیر این صورت (cj= sqrt(2)/sqrt(n
ما تبدیل کسینوسی را برای بلاک 8*8 (m*n)در نظر میگیریم و برای یک بلاک از دیتا آن را محاسبه میکنیم. همچنین برای سادگی کار تمامی داده ها را عدد 255 قرار دادیم. متغیر Pi نیز عدد پی با مقدار تقریبی 3.14 میباشد.
پیاده سازی تبدیل کسینوسی گسسته در جاوا
نوبت به پیاده سازی الگوریتم تبدیل کسینوسی گسسته رسیده است. برای این کار ما یک متد به نام dctTransform مینویسیم و ورودی آن را آرایهای از داده های خود قرار دادیم. کد این الگوریتم به صورت زیر است:
public class DCT {
public static int n = 8, m = 8;
public static double pi = 3.142857;
static strictfp void dctTransform(int matrix[][]) {
int i, j, k, l;
double[][] dct = new double[m][n];
double ci, cj, dct1, sum;
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) {
if (i == 0)
ci = 1 / Math.sqrt(m);
else
ci = Math.sqrt(2) / Math.sqrt(m);
if (j == 0)
cj = 1 / Math.sqrt(n);
else
cj = Math.sqrt(2) / Math.sqrt(n);
sum = 0;
for (k = 0; k < m; k++) {
for (l = 0; l < n; l++) {
dct1 = matrix[k][l] * Math.cos((2 * k + 1) * i * pi / (2 * m))
* Math.cos((2 * l + 1) * j * pi / (2 * n));
sum = sum + dct1;
}
}
dct[i][j] = ci * cj * sum;
}
}
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++)
System.out.printf("%f\t", dct[i][j]);
System.out.println();
}
}
public static void main(String[] args) {
int matrix[][] = { { 255, 255, 255, 255, 255, 255, 255, 255 },
{ 255, 255, 255, 255, 255, 255, 255, 255 },
{ 255, 255, 255, 255, 255, 255, 255, 255 },
{ 255, 255, 255, 255, 255, 255, 255, 255 },
{ 255, 255, 255, 255, 255, 255, 255, 255 },
{ 255, 255, 255, 255, 255, 255, 255, 255 },
{ 255, 255, 255, 255, 255, 255, 255, 255 },
{ 255, 255, 255, 255, 255, 255, 255, 255 } };
dctTransform(matrix);
}
}
بعد از محاسبه Ci و Cj که در بالا آنها را توضیح دادیم، به محاسبه قسمت دوم فرمول یعنی (sum(k=0 to m-1) sum(l=0 to n-1) پرداختیم. در این قسمت نیاز به دو حلقه برای محاسبه مجموع خواسته شده داریم. بعد از محاسبه قسمت دوم، با ضرب Ci و Cj و قسمت دوم، مقدار DCT برای سطر i و ستون j مشخص میشود. خروجی کد به صورت زیر است: