Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Jpeg алгоритм, проблемы при обратном преобразовании.

41K
06 сентября 2008 года
Shurikk
4 / / 06.09.2008
Пишу программку, которая будет показывать разницу между кодированием в Jpeg блоками 8х8 и

32х32, при этом реализую алгоритм до стадии сжатия по хаффману, то есть после квантования

начинаю обратное восстановление, так вот восстановленная матрица не соответствует правильной,

элементы остаются сконцентрированными в левом верхнем углу. Вот код для одной матрицы 32х32:
Код:
//---Получаю цвета с картинки-образца и перевожу их в 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);
        }
}

Знающие люди, просмотрите код, подскажите что не так... Может с цветами попутал что, может в алгоритме, может банально где-то опечатался...
14
08 сентября 2008 года
Phodopus
3.3K / / 19.06.2008
Мда, проанализировать код быстрее чем вы найдете ошибку боюсь у меня не выйдет, но вот могу подсказать что
Цитата:
для реальных изображений большинство значащих членов в новой матрице оказывается сгруппировано в левом верхнем углу (область малых скоростей изменения величин отсчетов в изображении), а правая нижняя часть матрицы (область больших скоростей) содержит члены с малыми значениями или вообще нулевые.


значит скорее всего в DCT (обратном DCT) где-то баг закрался :)

443
15 сентября 2008 года
REmindER
292 / / 23.03.2003
1. Скобку не там ставишь при расчете 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;
        }
    }


3. Коэффициенты для YCbCr->RGB у тебя давали смещение в красный спектр, я нашел немного другие, хотя не уверен, что они правильные (иногда составляющие цвета < 0 или > 255). Разбираться с этим что-то нет желания...

Не гарантирую правильнсть всего вышесказанного, т.к. сам не специалист :)
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог