Reputation: 27
I tried to write APP that would make DCT-2 transformation on image fragment and then transform back with inverse DCT-2. I have found code in c++/opencv that I tried to convert to C#, but somehow, I have different outcome at some point. Here is the code i tried to convert:
for (unsigned v = 0; v < BLOCK_SIZE; ++v)
{
for (unsigned u = 0; u < BLOCK_SIZE; ++u)
{
const double cu = (u == 0) ? 1.0 / sqrt(2) : 1.0;
const double cv = (v == 0) ? 1.0 / sqrt(2) : 1.0;
double dctCoeff = 0;
for (unsigned y = 0; y < BLOCK_SIZE; ++y)
{
for (unsigned x = 0; x < BLOCK_SIZE; ++x)
{
double uCosFactor = cos((double)(2 * x + 1) * M_PI * (double)u / (2 * (double) BLOCK_SIZE));
double vCosFactor = cos((double)(2 * y + 1) * M_PI * (double)v / (2 * (double) BLOCK_SIZE));
double pixel = (double)(lenaNoseGrey.at<unsigned char>(cv::Point(x,y)));
dctCoeff += pixel * uCosFactor * vCosFactor;
}
}
dctCoeff *= (2 / (double) BLOCK_SIZE) * cu * cv;
lenaNoseDct.at<double>(cv::Point(u,v)) = dctCoeff;
}
}
And here is mine:
for (int v = 0; v < BLOCK_SIZE; ++v)
{
for (int u = 0; u < BLOCK_SIZE; ++u)
{
double cu = (u == 0) ? 1.0 / Math.Sqrt(2) : 1.0;
double cv = (v == 0) ? 1.0 / Math.Sqrt(2) : 1.0;
double dctCoeff = 0;
double dctCoeffAlpha = 0;
for (int y1 = 0; y1 < BLOCK_SIZE; ++y1)
{
for (int x1 = 0; x1 < BLOCK_SIZE; ++x1)
{
double uCosFactor = Math.Cos((2 * x1 + 1) * Math.PI * u / (2 * (double)BLOCK_SIZE));
double vCosFactor = Math.Cos((2 * y1 + 1) * Math.PI * v / (2 * (double)BLOCK_SIZE));
double pixel = (double)bitmapaWy1.GetPixel((x1 + 284), (y1 + 313)).R;
double pixelalpha = (double)bitmapaWy1.GetPixel((x1 + 284), (y1 + 313)).A;
dctCoeff += pixel * uCosFactor * vCosFactor;
//dctCoeffAlpha += pixelalpha * uCosFactor * vCosFactor;
dctCoeffAlpha = pixelalpha;
}
}
dctCoeffAlpha *= (2 / (double)BLOCK_SIZE) * cu * cv;
dctCoeff *= (2 / (double)BLOCK_SIZE) * cu * cv;
macierz[u, v] = dctCoeff;
}
}
I have different outcome in my matrix, but when i convert matrix from the C++ code above with my inverse code, it works well. Can you find what have I done wrong? One difference I can spot is with getpixel method, but it is performed on exact same grayscaled image and image fragment that C++ code was performed.
When i inverse my matrix to image again, I can see image, but it has lot of random pixels that are too white, or too black.
Upvotes: 0
Views: 219
Reputation: 27
Problem is solved, the issue was too much code, actual code i posted works, problem was code I had after it, which was changing "dctcoeff" to byte and it was inside loop, so value of dct didnt reset to 0;
int BLOCK_SIZE = 16;
double[,] macierz = new double[16, 16];
for (int v = 0; v < BLOCK_SIZE; ++v)
{
for (int u = 0; u < BLOCK_SIZE; ++u)
{
double cu = (u == 0) ? 1.0 / Math.Sqrt(2) : 1.0;
double cv = (v == 0) ? 1.0 / Math.Sqrt(2) : 1.0;
double dctCoeff = 0;
for (int y1 = 0; y1 < BLOCK_SIZE; ++y1)
{
for (int x1 = 0; x1 < BLOCK_SIZE; ++x1)
{
double uCosFactor = Math.Cos((2 * x1 + 1) * Math.PI * u / (2 * (double)BLOCK_SIZE));
double vCosFactor = Math.Cos((2 * y1 + 1) * Math.PI * v / (2 * (double)BLOCK_SIZE));
double pixel = bitmapaWy1.GetPixel((x1 + 284), (y1 + 313)).R;
dctCoeff += pixel * uCosFactor * vCosFactor;
//dctCoeffAlpha += pixelalpha * uCosFactor * vCosFactor;
}
}
dctCoeff *= (2 / (double)BLOCK_SIZE) * cu * cv;
macierz[u, v] = dctCoeff;
}
}
This code works like a charm. I hope some good soul will use it, becouse i spent about 20h into making it work.
Upvotes: 1
Reputation: 16918
This is clearly a precision issue.
Most likely the problem is at the following line:
macierz[u, v] = dctCoeff;
I also have doubt in:
double pixel = (double)bitmapaWy1.GetPixel((x1 + 284), (y1 + 313)).R;
double pixelalpha = (double)bitmapaWy1.GetPixel((x1 + 284), (y1 + 313)).A;
dctCoeff += pixel * uCosFactor * vCosFactor;
//dctCoeffAlpha += pixelalpha * uCosFactor * vCosFactor;
dctCoeffAlpha = pixelalpha;
Upvotes: 0