问题描述
我听说应该可以在jpeg图像上进行无损旋转。这意味着您在没有IDCT的情况下在频域中进行旋转。我试过去谷歌但没找到任何东西。有人可以为此带来一些启示吗?
I've heard that it should be possible to do a lossless rotation on a jpeg image. That means you do the rotation in the frequency domain without an IDCT. I've tried to google it but haven't found anything. Could someone bring some light to this?
无意义的意思是我不会在轮换中丢失任何其他信息。当然,这可能只有在旋转90度的倍数时才有可能。
What I mean by lossless is that I don't lose any additional information in the rotation. And of course that's probably only possible when rotating multiples of 90 degrees.
推荐答案
你做不需要IDCT图像无损旋转(请注意无损旋转光栅图像仅适用于90度的倍数。)
You do not need to IDCT an image to rotate it losslessly (note that lossless rotation for raster images is only possible for angles that are multiples of 90 degrees).
以下步骤在DCT域中实现图像的转置:
The following steps achieve a transposition of the image, in the DCT domain:
- 转置每个DCT块的元素
- 转置每个DCT块的位置
我假设您已经可以执行以下操作:
I'm going to assume you can already do the following:
- 从JPEG图像中获取原始DCT系数(如果没有,请参阅)
- 将系数写回文件(如果要保存旋转的图像)
我无法向您展示完整的代码,因为它非常复杂,但这里是IDCT图像的位置(注意IDCT仅用于显示):
I can't show you the full code, because it's quite involved, but here's the bit where I IDCT the image (note the IDCT is for display purposes only):
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);
idct_step(dct_block, i/DCTSIZE, j/DCTSIZE, result);
}
这是显示的图片:
没有在这里发生了幻想 - 这只是原始图像。
Nothing fancy is happening here -- this is just the original image.
现在,这是实现两者我在上面提到的转置步骤的代码:
Now, here's the code that implements both the transposition steps I mentioned above:
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
}
这是结果图像:
您可以看到图像现在已转置。要实现正确的旋转,您需要将反射与换位相结合。
You can see that the image is now transposed. To achieve proper rotation, you need to combine reflection with transposition.
编辑
对不起,我忘记了反思也不是一件容易的事。它还包括两个步骤:
Sorry, I forgot that reflection is also not trivial. It also consists of two steps:
- 显然,反映每个DCT块在所需轴上的位置
- 不太明显,在每个 DCT块中反转(乘以-1)每个奇数行 OR 列。如果您正在垂直翻转,请反转奇数行。如果您正在水平翻转,请反转奇数列。
- Obviously, reflect the positions of each DCT block in the required axis
- Less obviously, invert (multiply by -1) each odd row OR column in each DCT block. If you're flipping vertically, invert odd rows. If you're flipping horizontally, invert odd columns.
这是执行垂直反射后的代码换位。
Here's code that performs a vertical reflection after the transposition.
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);
}
以下是您获得的图片:
你会注意到这构成逆时针旋转90度。
You will note that this constitutes a rotation by 90 degrees counter-clockwise.
这篇关于如何在频域中旋转图像?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!