Open zhongxiangrong opened 11 months ago
Hi @zhongxiangrong
If I remember correctly Matlab uses a different extension mode by default. PDWT always uses the periodic extension mode. Probably that's the cause of the discrepancy.
I just tried with
C = imread('ngc6543a.jpg');
I1 = C(:, :, 1);
imwrite(I1, "ngc6543a_gray.tif")
[LL,LH,HL,HH] = dwt2(I1,'haar', 'mode', 'ppd');
save("LL.mat", LL)
and on the other hand with the python wrapper to PDWT:
from tifffile import imread
from pycudwt import Wavelets
from scipy.io import loadmat
test_img = imread("ngc6543a_gray.tif")
W = Wavelets(test_img, "haar", 1)
W.forward()
LL = loadmat("LL.mat")["LL"] # result from matlab
print(np.max(np.abs(W.coeffs[0] - LL))) # 1e-13
which gives exactly the same result for the approximation coefficient.
Hi! @pierrepaleo Thank you very much for your answer. I later found out that the image was subjected to logarithmic operations in the MATLAB code, but not in my C++ code. Referring to your code, I saved the calculated LL component as a tif image in C++, and then used MATLAB to read the LL.tif file. After subtracting it, I found that the maximum error was 5.2871e-08. The wavelet coefficients of PDWT are similar to those of Matlab's wavelet transform.As for the histogram statistics after normalizing the LL, the results are as follows. In fact, the difference in histograms is due to the difference between MATLAB's imhist function and OpenCV's calchist function.
I have one more question. I have multiple GPUs. Can PDWT choose which specific GPU to perform cuda computation on? In addition, what do the memisonhost, do_separable, and do_cycle_spinning parameters in the Wavelets constructor represent? I look forward to your reply.
IIRC there is no explicit GPU choice parameter in the Wavelets()
class. Normally Cuda will automatically pick the "best" GPU at run-time. A way to manually pick a device is via the environment variable CUDA_VISIBLE_DEVICES
, though admittedly not ideal.
As for parameters:
memisonhost
indicates whether the image is on CPU memory rather than on device memory. If memisonhost=1
, a host-to-device copy (cudaMemcpyHostToDevice
) will be done.do_separable
indicates that the transform is separable, i.e that it can be performed as two 1D transforms rather than one 2D transform (same concept as convolution). The Discrete Wavelets Transform commonly found in the literature is separable and implemented as a filter bank. In the 2D case, LL
means "low-low" (low-pass filtering on rows, low-pass filtering on columns), LH
leans "low-high" (low-pass filtering on rows, high-pass filtering on columns), and so on. In practice this parameter is 1, unless you know what you are doing.do_cycle_spinning
is an advanced parameter indicating that a random circular-shift of the image is done before each transform. It serves only for iterative algorithms to reduce thresholding artefacts. It should be set to 0 unless you know what you are doing. Another way to avoid thresholding artefacts is the usage of stationary wavelets transform (undecimated transform) with do_swt=1
. There is a whole literature on the subject which I can't cover here.Hope this helps!
I tried to reproduce the 2D discrete wavelet transform in Matlab and PDWT, and then plotted a histogram of the cA parameter. The results are shown in the figure below, with red representing the result from Matlab and blue representing the result from PDWT. I would like to know what could be the possible reasons for this situation? This is my C++ code.
Wavelets w(img_f,rows,cols,"haar",1,1,1,0,0,2); w.forward(); w.get_coeff(LL, 0); //....change LL(float *) to LL(cv::Mat) cv::Mat hist_cA; const int bin = 256; float range[] = {0,255}; const float* histRange[] = {range}; cv::normalize(LL,LL,0,255,cv::NORM_MINMAX,-1); cv::calcHist(&LL,1,0,cv::Mat(),hist_cA,1,&bin,histRange,true);
This is the Matlab code.
[LL,LH,HL,HH] = dwt2(I1,'haar'); hist_cA = imhist(mat2gray(LL));