//---Получаю цвета с картинки-образца и перевожу их в YCbCr
int Lr[32][32]; int Lg[32][32]; int Lb[32][32];
int Ly[32][32]; int Lcb[32][32]; int Lcr[32][32];
for (int y=0; y<32; y++){
for (int x=0; x<32; x++){
Lr[x][y]=GetRValue(GetPixel(Image18->Picture->Bitmap->Canvas->Handle, x, y));
Lg[x][y]=GetGValue(GetPixel(Image18->Picture->Bitmap->Canvas->Handle, x, y));
Lb[x][y]=GetBValue(GetPixel(Image18->Picture->Bitmap->Canvas->Handle, x, y));
int R=Lr[x][y];int G=Lg[x][y]; int B=Lb[x][y];
Ly[x][y] = 0.299*R + 0.578*G + 0.114*B;
Lcb[x][y] = -0.1678*R - 0.3313*G + 0.5*B+128;
Lcr[x][y] = 0.5*R - 0.4187*G + 0.0813*B+128;
}
}
//-------------------------Создаю DCT и DCTT
float LDCT[32][32]; float LDCTT[32][32];
int n = 32;
float n2 = 0.25; //----корень из 2/32
for (int j=0; j<32; j++){
for (int i=0; i<32; i++){
if (i==0) LDCT[j]=1/sqrt(n);
if (i>0) LDCT[j]=n2*cos((2*j+1)*i*3.14)/(2*n);
LDCTT[j]=LDCT[j];
}
}
//------------------------Умножаю Lcb на DCTT и результат на DCT
int Ltmpcb[32][32]; int LREScb[32][32];
for(int i = 0; i < 32; i++)
for(int j = 0; j < 32; j++)
{
Ltmpcb[j] = 0;
for(int k = 0; k < 32; k++)
Ltmpcb[j] += (Lcb[k]*LDCTT[k][j]);
}
for(int i = 0; i < 32; i++)
for(int j = 0; j < 32; j++)
{
LREScb[j] = 0;
for(int k = 0; k < 32; k++)
LREScb[j] += (Ltmpcb[k] * LDCT[k][j]);
}
//--------------Квантование, создаем матрицу Q и делим на ее значения матрицу REScb
int q=StrToInt(LabeledEdit1->Text); //------коэфф. квантования
int LQ[32][32];
int LAcb[32][32];
for(int i=0;i<32;i++)
{
for(int j=0;j<32;j++){
LQ[j] = 1+((1+i+j)*q);
}
}
for(int i=0;i<32;i++)
{
for(int j=0;j<32;j++){
LAcb[j] = LREScb[j] / LQ[j];
}
}
//-------Все, сжатие делать не требуется, теперь восстанавливаем
//-----------------Умножаем на элементы матрицы квантования
int RLREScb[32][32];
for(int i=0;i<32;i++){
for(int j=0;j<32;j++)
RLREScb[j] =LAcb[j] * LQ[j];
}
//-----------------Умножаем на матрицу DCT
int RLtmpcb[32][32];
for(int i = 0; i < 32; i++){
for(int j = 0; j < 32; j++){
RLtmpcb[j] = 0;
for(int k = 0; k < 32; k++)
RLtmpcb[j] += (RLREScb[k] * LDCT[k][j]);
}
}
//-----------------Умножаем на матрицу DCTT
int RLcb[32][32];
for(int i = 0; i < 32; i++){
for(int j = 0; j < 32; j++){
RLcb[j] = 0;
for(int k = 0; k < 32; k++)
RLcb[j] += (RLtmpcb[k] * LDCTT[k][j]);
}
}
//----------------Переводим цвета в RGB
int RLr[32][32];
int RLg[32][32];
int RLb[32][32];
for (int y=0; y<32; y++){
for (int x=0; x<32; x++){
int cy=Ly[x][y];
int cb=RLcb[x][y]-128;
int cr=RLcr[x][y]-128;
RLr[x][y] = cy+(1.4075*cr);
RLg[x][y] = cy-(0.3455*cb)-(0.7169*cr);
RLb[x][y] = cy+(1.7790*cb);
}
}
Jpeg алгоритм, проблемы при обратном преобразовании.
32х32, при этом реализую алгоритм до стадии сжатия по хаффману, то есть после квантования
начинаю обратное восстановление, так вот восстановленная матрица не соответствует правильной,
элементы остаются сконцентрированными в левом верхнем углу. Вот код для одной матрицы 32х32:
Код:
Знающие люди, просмотрите код, подскажите что не так... Может с цветами попутал что, может в алгоритме, может банально где-то опечатался...
Цитата:
для реальных изображений большинство значащих членов в новой матрице оказывается сгруппировано в левом верхнем углу (область малых скоростей изменения величин отсчетов в изображении), а правая нижняя часть матрицы (область больших скоростей) содержит члены с малыми значениями или вообще нулевые.
значит скорее всего в DCT (обратном DCT) где-то баг закрался :)
Код:
LDCT[j]=n2*cos((2*j+1)*i*M_PI/(2*n))
2. DCT преобразование: V = MDCT*T*Mtrasposed, поэтому соблюдай порядок умножения (A*B != B*A):
Код:
const int n = 32;
int Lr[n][n], Lg[n][n], Lb[n][n];
int Ly[n][n], Lcb[n][n], Lcr[n][n];
for (int y = 0; y < n; y ++)
{
for (int x = 0; x < n; x ++)
{
Lr[x][y] = GetRValue(GetPixel(Image18->Picture->Bitmap->Canvas->Handle, x, y));
Lg[x][y] = GetGValue(GetPixel(Image18->Picture->Bitmap->Canvas->Handle, x, y));
Lb[x][y] = GetBValue(GetPixel(Image18->Picture->Bitmap->Canvas->Handle, x, y));
int R = Lr[x][y];
int G = Lg[x][y];
int B = Lb[x][y];
Ly[x][y] = 0.299 * R + 0.587 * G + 0.114 * B ;
Lcb[x][y] = - 0.1687 * R - 0.3313 * G + 0.5 * B + 128;
Lcr[x][y] = 0.5 * R - 0.4187 * G - 0.0813 * B + 128;
}
}
//-------------------------Создаю DCT и DCTT
float LDCT[n][n], LDCTT[n][n];
float n2 = sqrt(2 / n);
for (int i = 0; i < n; i ++)
{
for (int j = 0; j < n; j ++)
{
if(i == 0)
LDCT[j] = 1 / sqrt(n);
else
LDCT[j] = n2 * cos((2 * j + 1) * i * M_PI / (2 * n));
LDCTT[j] = LDCT[j];
}
}
//------------------------Умножаю Lcb на DCT и результат на DCTT
int Ltmpcb[n][n], LREScb[n][n];
int Ltmpcr[n][n], LREScr[n][n];
for(int i = 0; i < n; i ++)
{
for(int j = 0; j < n; j ++)
{
Ltmpcb[j] = 0;
Ltmpcr[j] = 0;
for(int k = 0; k < n; k++)
{
Ltmpcb[j] += (LDCT[k] * Lcb[k][j]);
Ltmpcr[j] += (LDCT[k] * Lcr[k][j]);
}
}
}
for(int i = 0; i < n; i ++)
{
for(int j = 0; j < n; j ++)
{
LREScb[j] = 0;
LREScr[j] = 0;
for(int k = 0; k < n; k++)
{
LREScb[j] += (Ltmpcb[k] * LDCTT[k][j]);
LREScr[j] += (Ltmpcr[k] * LDCTT[k][j]);
}
}
}
//--------------Квантование, создаем матрицу Q и делим на ее значения матрицу REScb
int q = StrToInt(LabeledEdit1->Text); //------коэфф. квантования
int LQ[n][n];
int LAcb[n][n], LAcr[n][n];
for(int i = 0; i < n; i ++)
{
for(int j = 0; j < n; j ++)
{
LQ[j] = 1 + ((1 + i + j) * q);
}
}
for(int i = 0; i < n; i ++)
{
for(int j = 0; j < n; j++)
{
LAcb[j] = LREScb[j] / LQ[j];
LAcr[j] = LREScr[j] / LQ[j];
}
}
//-------Все, сжатие делать не требуется, теперь восстанавливаем
//-----------------Умножаем на элементы матрицы квантования
int RLREScb[n][n], RLREScr[n][n];
for(int i = 0; i < n; i ++)
{
for(int j=0;j<n;j++)
{
RLREScb[j] = LAcb[j] * LQ[j];
RLREScr[j] = LAcr[j] * LQ[j];
}
}
//-----------------Умножаем на матрицу DCTT
int RLtmpcb[n][n], RLtmpcr[n][n];
for(int i = 0; i < n; i ++)
{
for(int j = 0; j < n; j ++)
{
RLtmpcb[j] = 0;
RLtmpcr[j] = 0;
for(int k = 0; k < n; k++)
{
RLtmpcb[j] += (LDCTT[k] * RLREScb[k][j]);
RLtmpcr[j] += (LDCTT[k] * RLREScr[k][j]);
}
}
}
//-----------------Умножаем на матрицу DCT
int RLcb[n][n], RLcr[n][n];
for(int i = 0; i < n; i ++)
{
for(int j = 0; j < n; j ++)
{
RLcb[j] = 0;
RLcr[j] = 0;
for(int k = 0; k < n; k ++)
{
RLcb[j] += (RLtmpcb[k] * LDCT[k][j]);
RLcr[j] += (RLtmpcr[k] * LDCT[k][j]);
}
}
}
//----------------Переводим цвета в RGB
int RLr[n][n], RLg[n][n], RLb[n][n];
for(int y = 0; y < n; y ++)
{
for (int x = 0; x < n; x ++)
{
int cy = Ly[x][y];
int cb = RLcb[x][y] - 128;
int cr = RLcr[x][y] - 128;
RLr[x][y] = cy + (1.402 * cr);
//if(RLr[x][y] > 255) RLr[x][y] = 255;
//if(RLr[x][y] < 0) RLr[x][y] = 0;
RLg[x][y] = cy - (0.34414 * cb) - (0.71414 * cr);
//if(RLg[x][y] > 255) RLg[x][y] = 255;
//if(RLg[x][y] < 0) RLg[x][y] = 0;
RLb[x][y] = cy + (1.772 * cb);
//if(RLb[x][y] > 255) RLb[x][y] = 255;
//if(RLb[x][y] < 0) RLb[x][y] = 0;
}
}
int Lr[n][n], Lg[n][n], Lb[n][n];
int Ly[n][n], Lcb[n][n], Lcr[n][n];
for (int y = 0; y < n; y ++)
{
for (int x = 0; x < n; x ++)
{
Lr[x][y] = GetRValue(GetPixel(Image18->Picture->Bitmap->Canvas->Handle, x, y));
Lg[x][y] = GetGValue(GetPixel(Image18->Picture->Bitmap->Canvas->Handle, x, y));
Lb[x][y] = GetBValue(GetPixel(Image18->Picture->Bitmap->Canvas->Handle, x, y));
int R = Lr[x][y];
int G = Lg[x][y];
int B = Lb[x][y];
Ly[x][y] = 0.299 * R + 0.587 * G + 0.114 * B ;
Lcb[x][y] = - 0.1687 * R - 0.3313 * G + 0.5 * B + 128;
Lcr[x][y] = 0.5 * R - 0.4187 * G - 0.0813 * B + 128;
}
}
//-------------------------Создаю DCT и DCTT
float LDCT[n][n], LDCTT[n][n];
float n2 = sqrt(2 / n);
for (int i = 0; i < n; i ++)
{
for (int j = 0; j < n; j ++)
{
if(i == 0)
LDCT[j] = 1 / sqrt(n);
else
LDCT[j] = n2 * cos((2 * j + 1) * i * M_PI / (2 * n));
LDCTT[j] = LDCT[j];
}
}
//------------------------Умножаю Lcb на DCT и результат на DCTT
int Ltmpcb[n][n], LREScb[n][n];
int Ltmpcr[n][n], LREScr[n][n];
for(int i = 0; i < n; i ++)
{
for(int j = 0; j < n; j ++)
{
Ltmpcb[j] = 0;
Ltmpcr[j] = 0;
for(int k = 0; k < n; k++)
{
Ltmpcb[j] += (LDCT[k] * Lcb[k][j]);
Ltmpcr[j] += (LDCT[k] * Lcr[k][j]);
}
}
}
for(int i = 0; i < n; i ++)
{
for(int j = 0; j < n; j ++)
{
LREScb[j] = 0;
LREScr[j] = 0;
for(int k = 0; k < n; k++)
{
LREScb[j] += (Ltmpcb[k] * LDCTT[k][j]);
LREScr[j] += (Ltmpcr[k] * LDCTT[k][j]);
}
}
}
//--------------Квантование, создаем матрицу Q и делим на ее значения матрицу REScb
int q = StrToInt(LabeledEdit1->Text); //------коэфф. квантования
int LQ[n][n];
int LAcb[n][n], LAcr[n][n];
for(int i = 0; i < n; i ++)
{
for(int j = 0; j < n; j ++)
{
LQ[j] = 1 + ((1 + i + j) * q);
}
}
for(int i = 0; i < n; i ++)
{
for(int j = 0; j < n; j++)
{
LAcb[j] = LREScb[j] / LQ[j];
LAcr[j] = LREScr[j] / LQ[j];
}
}
//-------Все, сжатие делать не требуется, теперь восстанавливаем
//-----------------Умножаем на элементы матрицы квантования
int RLREScb[n][n], RLREScr[n][n];
for(int i = 0; i < n; i ++)
{
for(int j=0;j<n;j++)
{
RLREScb[j] = LAcb[j] * LQ[j];
RLREScr[j] = LAcr[j] * LQ[j];
}
}
//-----------------Умножаем на матрицу DCTT
int RLtmpcb[n][n], RLtmpcr[n][n];
for(int i = 0; i < n; i ++)
{
for(int j = 0; j < n; j ++)
{
RLtmpcb[j] = 0;
RLtmpcr[j] = 0;
for(int k = 0; k < n; k++)
{
RLtmpcb[j] += (LDCTT[k] * RLREScb[k][j]);
RLtmpcr[j] += (LDCTT[k] * RLREScr[k][j]);
}
}
}
//-----------------Умножаем на матрицу DCT
int RLcb[n][n], RLcr[n][n];
for(int i = 0; i < n; i ++)
{
for(int j = 0; j < n; j ++)
{
RLcb[j] = 0;
RLcr[j] = 0;
for(int k = 0; k < n; k ++)
{
RLcb[j] += (RLtmpcb[k] * LDCT[k][j]);
RLcr[j] += (RLtmpcr[k] * LDCT[k][j]);
}
}
}
//----------------Переводим цвета в RGB
int RLr[n][n], RLg[n][n], RLb[n][n];
for(int y = 0; y < n; y ++)
{
for (int x = 0; x < n; x ++)
{
int cy = Ly[x][y];
int cb = RLcb[x][y] - 128;
int cr = RLcr[x][y] - 128;
RLr[x][y] = cy + (1.402 * cr);
//if(RLr[x][y] > 255) RLr[x][y] = 255;
//if(RLr[x][y] < 0) RLr[x][y] = 0;
RLg[x][y] = cy - (0.34414 * cb) - (0.71414 * cr);
//if(RLg[x][y] > 255) RLg[x][y] = 255;
//if(RLg[x][y] < 0) RLg[x][y] = 0;
RLb[x][y] = cy + (1.772 * cb);
//if(RLb[x][y] > 255) RLb[x][y] = 255;
//if(RLb[x][y] < 0) RLb[x][y] = 0;
}
}
3. Коэффициенты для YCbCr->RGB у тебя давали смещение в красный спектр, я нашел немного другие, хотя не уверен, что они правильные (иногда составляющие цвета < 0 или > 255). Разбираться с этим что-то нет желания...
Не гарантирую правильнсть всего вышесказанного, т.к. сам не специалист :)