关于OpenCV中DCT函数方程及Scilab JPEG压缩实现的疑问
Hey there! Let's break down how OpenCV's dct function maps to the equation you're using in your Scilab code for JPEG compression—since you're comparing results between Scilab's built-in imdct and your custom my_function on the Lenna image, this should clear up the confusion.
First: Your Scilab Equation Context
From what you've shared, your my_function uses the standard 8x8 2D DCT-II (the industry standard for JPEG), which looks like this (assuming you're working with inverse DCT, since you mentioned imdct):
For an 8x8 block of DCT coefficients ( X(u,v) ), the inverse transform to recover the pixel block ( x(i,j) ) is:
[
x(i,j) = \frac{1}{4} \sum_{u=0}^{7} \sum_{v=0}^{7} C(u)C(v) X(u,v) \cos\left( \frac{(2i+1)u\pi}{16} \right) \cos\left( \frac{(2j+1)v\pi}{16} \right)
]
Where the scaling factors ( C(k) ) are:
- ( C(0) = \frac{1}{\sqrt{2}} )
- ( C(k) = 1 ) for ( k = 1,2,...,7 )
OpenCV's Corresponding DCT Equation
OpenCV's dct function implements the exact same JPEG-compliant DCT-II, but with one key difference: default scaling. Here's the breakdown for both forward and inverse transforms:
Forward DCT (Compression Step)
OpenCV's forward DCT (called with cv::dct(src, dst, DCT_FORWARD)) calculates coefficients as:
[
dst(u,v) = C(u)C(v) \sum_{i=0}^{7} \sum_{j=0}^{7} x(i,j) \cos\left( \frac{(2i+1)u\pi}{16} \right) \cos\left( \frac{(2j+1)v\pi}{16} \right)
]
Notice this omits the ( \frac{1}{4} ) scaling factor present in your Scilab equation. To match Scilab's forward DCT output, divide OpenCV's result by 4.
Inverse DCT (Decompression Step)
For inverse transforms (what imdct handles), OpenCV's inverse DCT (called with cv::dct(src, dst, DCT_INVERSE)) outputs:
[
dst(i,j) = \sum_{u=0}^{7} \sum_{v=0}^{7} C(u)C(v) X(u,v) \cos\left( \frac{(2i+1)u\pi}{16} \right) \cos\left( \frac{(2j+1)v\pi}{16} \right)
]
Again, no ( \frac{1}{4} ) scaling—so to get results matching Scilab's imdct, divide OpenCV's inverse DCT output by 4.
Quick Verification Steps for Lenna Image
To confirm alignment between your code and OpenCV:
- Grab an 8x8 pixel block from Lenna, shift values to the JPEG standard range (-128 to 127, since JPEG centers pixels around 0).
- Compute forward DCT in Scilab and OpenCV, then divide OpenCV's output by 4—you should get identical coefficient values.
- For inverse DCT: take the same DCT coefficients, run Scilab's
imdctand OpenCV's inverse DCT, then divide OpenCV's result by 4—pixel values should match.
Key Takeaway
OpenCV's dct uses the exact same mathematical core as your Scilab equation; the only gap is the default scaling factor. Add a division by 4 to OpenCV's forward/inverse results, and you'll get perfect alignment with your my_function and Scilab's imdct.
内容的提问来源于stack exchange,提问作者Chris Tine

