Problem with different outcome with DCT transformation on image while converting C++ to C#

时间:2018-09-18 19:52:43

标签: c# opencv image-processing dct

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.

2 个答案:

答案 0 :(得分:1)

问题已解决,问题是代码太多,我发布的实际代码有效,问题是我拥有的代码,正在将“ dctcoeff”更改为字节并且在内部循环中,因此dct的值未重置为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;

            }
        }

此代码的作用就像一个超级魅力。我希望有好心人会使用它,因为我花了大约20个小时使它起作用。

答案 1 :(得分:0)

这显然是一个精度问题。

最可能的问题是在以下行:

 macierz[u, v] = dctCoeff;

我也有以下疑问:

            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;
相关问题