生成AIはプログラムに使えるか?
結局、アルゴリズムを知らないと使えない。取りあえず単純かつ極端な例をあげてみる。これはJPEGデコーダの一部IDCTの部分の実装になる。
Q. pythonで8x8のDCTを逆変換する関数を書いて
import numpy as np
def idct_8x8(dct_coeffs):
"""
Perform inverse Discrete Cosine Transform (IDCT) on an 8x8 block.
Args:
- dct_coeffs: 8x8 array of DCT coefficients
Returns:
- img: 8x8 array of pixel values (uint8)
"""
alpha = np.zeros((8, 8))
alpha[0, :] = 1 / np.sqrt(8)
alpha[1:, :] = np.sqrt(2 / 8)
img = np.zeros((8, 8))
for u in range(8):
for v in range(8):
sum_val = 0
for x in range(8):
for y in range(8):
sum_val += alpha[x, u] * alpha[y, v] * dct_coeffs[x, y] * np.cos((2 * x + 1) * u * np.pi / 16) * np.cos((2 * y + 1) * v * np.pi / 16)
img[u, v] = sum_val
img = np.clip(img + 128, 0, 255).astype(np.uint8)
return img
このコード恐らく正しいと思うけど、検証に時間がかかるのでパス。そもそもこのコードはダメ。理由は遅すぎて使えない。
Cでも変わらぬ
#include <stdio.h>
#include <math.h>
#define N 8
void idct_8x8(float dct_coeffs[N][N], unsigned char img[N][N]) {
float alpha[N][N];
int u, v, x, y;
for (u = 0; u < N; u++) {
for (v = 0; v < N; v++) {
if (u == 0)
alpha[u][v] = 1.0 / sqrt(N);
else
alpha[u][v] = sqrt(2.0 / N);
}
}
for (u = 0; u < N; u++) {
for (v = 0; v < N; v++) {
float sum_val = 0.0;
for (x = 0; x < N; x++) {
for (y = 0; y < N; y++) {
sum_val += alpha[x][u] * alpha[y][v] * dct_coeffs[x][y] *
cos((2 * x + 1) * u * M_PI / (2 * N)) *
cos((2 * y + 1) * v * M_PI / (2 * N));
}
}
img[u][v] = (unsigned char)(sum_val + 128);
}
}
}
だから使い物にならないと。そもそもcos関数が遅い。
現在使われて居るライブラリの100倍以上遅くなるかと……。GPUで8x8行列を一度に計算すればあまり差は出ないかも知れないけど。
Q. LL&M : The Loeffler-Ligtenberg-Moschytz (LLM) algorithm を使ってください
#include <stdio.h>
#include <math.h>
#define N 8
void idct_8x8(float dct_coeffs[N][N], unsigned char img[N][N]) {
int x, y, u, v;
float F[N][N];
float CU[N], CV[N];
float tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
float tmp10, tmp11, tmp12, tmp13;
float z1, z2, z3, z4, z5;
// Precompute CU and CV
for (u = 0; u < N; u++) {
CU[u] = (u == 0) ? 1.0 / sqrt(2) : 1.0;
CV[u] = (u == 0) ? 1.0 / sqrt(2) : 1.0;
}
// Compute intermediate variables
for (x = 0; x < N; x++) {
for (y = 0; y < N; y++) {
float sum = 0.0;
for (u = 0; u < N; u++) {
for (v = 0; v < N; v++) {
sum += dct_coeffs[u][v] * cos((2 * x + 1) * u * M_PI / 16) * cos((2 * y + 1) * v * M_PI / 16) *
CU[u] * CV[v];
}
}
F[x][y] = sum * 0.25;
}
}
// Compute output values
for (x = 0; x < N; x += 2) {
for (y = 0; y < N; y += 2) {
tmp0 = F[x][y] + F[x][y+1];
tmp1 = F[x][y] - F[x][y+1];
tmp2 = F[x+1][y] + F[x+1][y+1];
tmp3 = F[x+1][y] - F[x+1][y+1];
tmp10 = tmp0 + tmp2;
tmp13 = tmp0 - tmp2;
tmp11 = tmp1 + tmp3;
tmp12 = tmp1 - tmp3;
img[x][y] = (unsigned char)(tmp10 + tmp11);
img[x][y+1] = (unsigned char)(tmp12 + tmp13);
img[x+1][y] = (unsigned char)(tmp10 - tmp11);
img[x+1][y+1] = (unsigned char)(tmp13 - tmp12);
}
}
}
半分しか適用されていない……。
この記事が気に入ったらサポートをしてみませんか?