Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Image processing 如何在频域中旋转图像?_Image Processing_Image Manipulation_Jpeg_Image Rotation - Fatal编程技术网

Image processing 如何在频域中旋转图像?

Image processing 如何在频域中旋转图像?,image-processing,image-manipulation,jpeg,image-rotation,Image Processing,Image Manipulation,Jpeg,Image Rotation,我听说应该可以对jpeg图像进行无损旋转。这意味着在没有IDCT的情况下,在频域中进行旋转。我试着用谷歌搜索,但什么也没找到。有人能解释一下吗 我所说的无损的意思是,在旋转过程中,我不会丢失任何额外的信息。当然,这可能只有在旋转90度的倍数时才可能 您不需要对图像进行IDCT以无损旋转(请注意,光栅图像的无损旋转仅适用于90度倍数的角度) 以下步骤在DCT域中实现图像的转置: 转置每个DCT块的元素 变换每个DCT块的位置 我假设您已经可以执行以下操作: 从JPEG图像中获取原始DCT系数(如

我听说应该可以对jpeg图像进行无损旋转。这意味着在没有IDCT的情况下,在频域中进行旋转。我试着用谷歌搜索,但什么也没找到。有人能解释一下吗


我所说的无损的意思是,在旋转过程中,我不会丢失任何额外的信息。当然,这可能只有在旋转90度的倍数时才可能

您不需要对图像进行IDCT以无损旋转(请注意,光栅图像的无损旋转仅适用于90度倍数的角度)

以下步骤在DCT域中实现图像的转置:

  • 转置每个DCT块的元素
  • 变换每个DCT块的位置
  • 我假设您已经可以执行以下操作:

    • 从JPEG图像中获取原始DCT系数(如果不是,请参阅)
    • 将系数写回文件(如果要保存旋转的图像)
    我无法向您展示完整的代码,因为它非常复杂,但这里是我插入图像的位置(注意,插入图像仅用于显示目的)

    Size s=coeff.Size();
    Mat结果=cv::Mat::零(s.高度、s.宽度、cv_8UC1);
    对于(int i=0;i
    这是显示的图像:

    这里没有什么新奇的事情发生——这只是原始图像

    下面是实现上述转置步骤的代码:

    Size s = coeff.size();
    Mat result = cv::Mat::zeros(s.height, s.width, CV_8UC1);
    
    for (int i = 0; i < s.height - DCTSIZE + 1; i += DCTSIZE)
    for (int j = 0; j < s.width  - DCTSIZE + 1; j += DCTSIZE)
    {
        Rect rect = Rect(j, i, DCTSIZE, DCTSIZE);
        Mat dct_block = cv::Mat::Mat(coeff, rect);
        Mat dct_bt(cv::Size(DCTSIZE, DCTSIZE), coeff.type());
        cv::transpose(dct_block, dct_bt);                // First transposition
        idct_step(dct_bt, j/DCTSIZE, i/DCTSIZE, result); // Second transposition, swap i and j
    }
    
    Size s=coeff.Size();
    Mat结果=cv::Mat::零(s.高度、s.宽度、cv_8UC1);
    对于(int i=0;i
    这是生成的图像:

    您可以看到图像现在已转置。要实现正确的旋转,需要将反射与换位相结合

    编辑

    对不起,我忘了反思也不是小事。它还包括两个步骤:

  • 显然,反映每个DCT块在所需轴上的位置
  • 不太明显的是,反转(乘以-1)每个DCT块中的每个奇数行列。如果垂直翻转,则反转奇数行。如果水平翻转,则反转奇数
  • 下面是在换位后执行垂直反射的代码

    for (int i = 0; i < s.height - DCTSIZE + 1; i += DCTSIZE)
    for (int j = 0; j < s.width  - DCTSIZE + 1; j += DCTSIZE)
    {
        Rect rect = Rect(j, i, DCTSIZE, DCTSIZE);
        Mat dct_block = cv::Mat::Mat(coeff, rect);
    
        Mat dct_bt(cv::Size(DCTSIZE, DCTSIZE), coeff.type());
        cv::transpose(dct_block, dct_bt);
    
        // This is the less obvious part of the reflection.
        Mat dct_flip = dct_bt.clone();
        for (int k = 1; k < DCTSIZE; k += 2)
        for (int l = 0; l < DCTSIZE; ++l)
            dct_flip.at<double>(k, l) *= -1;
    
        // This is the more obvious part of the reflection.
        idct_step(dct_flip, (s.width - j - DCTSIZE)/DCTSIZE, i/DCTSIZE, result);
    }
    
    for(int i=0;i
    以下是您获得的图像:


    您会注意到,这是一个逆时针旋转90度的过程。

    libjpeg@datenwolf中包含了一个名为jpegtran的程序,它实现了所有这一切:谢谢。用它肯定比你自己滚要好。不过没那么有趣:)
    for (int i = 0; i < s.height - DCTSIZE + 1; i += DCTSIZE)
    for (int j = 0; j < s.width  - DCTSIZE + 1; j += DCTSIZE)
    {
        Rect rect = Rect(j, i, DCTSIZE, DCTSIZE);
        Mat dct_block = cv::Mat::Mat(coeff, rect);
    
        Mat dct_bt(cv::Size(DCTSIZE, DCTSIZE), coeff.type());
        cv::transpose(dct_block, dct_bt);
    
        // This is the less obvious part of the reflection.
        Mat dct_flip = dct_bt.clone();
        for (int k = 1; k < DCTSIZE; k += 2)
        for (int l = 0; l < DCTSIZE; ++l)
            dct_flip.at<double>(k, l) *= -1;
    
        // This is the more obvious part of the reflection.
        idct_step(dct_flip, (s.width - j - DCTSIZE)/DCTSIZE, i/DCTSIZE, result);
    }