How do I rotate an image in the frequency domain? -
i've heard should possible lossless rotation on jpeg image. means rotation in frequency domain without idct. i've tried google haven't found anything. bring light this?
what mean lossless don't lose additional information in rotation. , of course that's possible when rotating multiples of 90 degrees.
you not need idct image rotate losslessly (note lossless rotation raster images possible angles multiples of 90 degrees).
the following steps achieve transposition of image, in dct domain:
- transpose elements of each dct block
- transpose positions of each dct block
i'm going assume can following:
- grab raw dct coefficients jpeg image (if not, see here)
- write coefficients file (if want save rotated image)
i can't show full code, because it's quite involved, here's bit idct image (note idct display purposes only):
size s = coeff.size(); mat result = cv::mat::zeros(s.height, s.width, cv_8uc1); (int = 0; < s.height - dctsize + 1; += dctsize) (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); }
this image shown:
nothing fancy happening here -- original image.
now, here's code implements both transposition steps mentioned above:
size s = coeff.size(); mat result = cv::mat::zeros(s.height, s.width, cv_8uc1); (int = 0; < s.height - dctsize + 1; += dctsize) (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 , j }
this resulting image:
you can see image transposed. achieve proper rotation, need combine reflection transposition.
edit
sorry, forgot reflection not trivial. consists of 2 steps:
- obviously, reflect positions of each dct block in required axis
- less obviously, invert (multiply -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 performs vertical reflection after transposition.
for (int = 0; < s.height - dctsize + 1; += dctsize) (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); // less obvious part of reflection. mat dct_flip = dct_bt.clone(); (int k = 1; k < dctsize; k += 2) (int l = 0; l < dctsize; ++l) dct_flip.at<double>(k, l) *= -1; // more obvious part of reflection. idct_step(dct_flip, (s.width - j - dctsize)/dctsize, i/dctsize, result); }
here's image get:
you note constitutes rotation 90 degrees counter-clockwise.
Comments
Post a Comment