Wrong result after converting image from floating-point to unsigned in implementing JPEG

72 views Asked by At

I have a problem with my code in implementing the JPEG compression using OpenCV and C++. On the encoder and after the code does the DCT when I add a line of code, which converts the planes from 32-bit floating-point to 8-bit unsigned, I get some weird output as you can see below. After this conversion, besides the fact that the result is not acceptable (cause I didn't even write the quantization part yet) even the original image is affected by this line of code. When changing this conversion to 16-bit unsigned, the original image is untouched and the decoded image becomes better, but the result is still not acceptable.

constexpr int blocksize = 8;

struct block {
    cv::Rect roi;
    cv::Mat subimage;
};

int main()
{
    //Reading the image and storing its necessary information
    std::string addr("C:\\Users\\lena.jpg");
    const cv::Mat img = cv::imread(addr, cv::IMREAD_COLOR);
    if (img.empty()) {
        std::cerr << "Could not open the image!" << std::endl;
        return -1;
}
int height = img.size().height;
int width = img.size().width;
std::cout << "width * height: " << width << " * " << height << std::endl;

//Constructing 8 by 8 blocks
std::vector<block> blocks;

for (int y = 0; y < height; y += blocksize){
    for (int x = 0; x < width; x += blocksize){
        int block_width = std::min(blocksize, width - x);
        int block_height = std::min(blocksize, height - y);
        block temp;
        cv::Rect newROI(x, y, block_width, block_height);
        temp.roi = newROI;
        temp.subimage = img(newROI);
        blocks.push_back(temp);
    }
}
//Discrete Cosine Transformation and Quantization
for (int bIdx = 0; bIdx < blocks.size(); ++bIdx) {
    std::vector<cv::Mat> planes;
    cv::split(blocks[bIdx].subimage, planes);

    std::vector<cv::Mat> resultPlanes(planes.size());
    for (int k = 0; k < planes.size(); ++k) {
        planes[k].convertTo(planes[k], CV_32FC1);

            cv::dct(planes[k], resultPlanes[k]);
            //The line that I mentioned above
            resultPlanes[k].convertTo(resultPlanes[k], CV_8UC1);
        }
        cv::merge(resultPlanes, blocks[bIdx].subimage);
}

//Inverse of DCT and Quantization
for (int bIdx = 0; bIdx < blocks.size(); ++bIdx) {
    std::vector<cv::Mat> planes;
    cv::split(blocks[bIdx].subimage, planes);

    std::vector<cv::Mat> resultPlanes(planes.size());
    for (int k = 0; k < planes.size(); ++k) {
        planes[k].convertTo(planes[k], CV_32FC1);
        cv::idct(planes[k], resultPlanes[k]);
        
        resultPlanes[k].convertTo(resultPlanes[k], CV_8UC1);
    }
    cv::merge(resultPlanes, blocks[bIdx].subimage);
}

//Reconstructing the whole image
cv::Mat modifiedImg = img.clone();
for (int bIdx = 0; bIdx < blocks.size(); ++bIdx) {
    blocks[bIdx].subimage.copyTo(modifiedImg(blocks[bIdx].roi));
}

//Show the result
cv::imshow("JPEG", img);
cv::imshow("My JPEG", modifiedImg);
cv::waitKey(0);
}

enter image description here

enter image description here

enter image description here

0

There are 0 answers