1

javacode から 2D Discrete Wavelet-Transformation を実装しました (こちらを参照)。元のコードを Java で実行すると、結果は問題ないように見えます。しかし、私の C++ 実装では、結果が歪んでいます。理由はわかりません(写真参照)。元の画像: 元の画像 失敗した dwt: dwt デイラー

これはopencvマットと配列の変換による問題でしょうか?それとも、これは dwt 実装のバグですか?

main.cpp

#include <math.h>
#include "dwt_cdf_9_7.h"
#include "dwt.c";
#include "opencv/cv.h";

void analyze(cv::Mat img) {
int cols = img.cols;
int rows = img.rows;
/* convert image to grayscale */
cv::Mat gray8 = cv::Mat(rows, cols, CV_8UC1);
cv::cvtColor(img, gray8, CV_BGR2GRAY);

/* resize */
if(rows % 2 != 0 || cols % 2 != 0) {
    rows -= rows%8;
    cols -= cols%8;
    cv::Size s = cv::Size(rows, cols);
    cv::Mat resized = cv::Mat(s, CV_8UC1);
    cv::resize(gray8, resized, s);
    gray8=resized;
}
cv::Mat gray32 = cv::Mat(cols, rows, CV_32FC1);
gray8.convertTo(gray32, CV_32FC1);
//reshape image
cv::Mat reshape = gray32.reshape ( 0, 1 );
std::vector<float> v_float(reshape.begin<float>(), reshape.end<float>());
std::vector<int> v_int(v_float.begin(), v_float.end());
int* block= v_int.data();
//get dwt
DWT_CDF_9_7 dwt(cols,rows,3);
block=dwt.forward(block,0);
std::vector<float> v_float2(v_int.begin(), v_int.end());
float* block2= &v_float2[0];
cv::Mat dwt_reshaped(cols,rows,CV_32FC1,v_float2.data());
cv::normalize(dwt_reshaped, dwt_reshaped, 0, 255, CV_MINMAX);
imwrite("res.jpg",dwt_reshaped);
}

dwt_cdf_9_7.h

 #ifndef DWT_CDF_9_7_H 
 #define DWT_CDF_9_7_H

 class DWT_CDF_9_7
{
public:
DWT_CDF_9_7(int dim);
DWT_CDF_9_7(int width, int height);
DWT_CDF_9_7(int width, int height, int steps);

int *data;
int width;
int height;
int steps;

int* forward(int block[], int blkptr);
int* inverse(int block[], int blkptr);

private:
static const int SHIFT  = 12;
static const int ADJUST = 1 << (SHIFT - 1);

static const int PREDICT_1 = 6497; // with SHIFT = 12
static const int UPDATE_1  = 217;  // with SHIFT = 12
static const int PREDICT_2 = 3616; // with SHIFT = 12
static const int UPDATE_2  = 1817; // with SHIFT = 12
static const int SCALING_1 = 4709; // with SHIFT = 12
static const int SCALING_2 = 3562; // with SHIFT = 12


int* forward(int block[], int blkptr, int stride, int inc, int dim1, int dim2);
int* inverse(int block[], int blkptr, int stride, int inc, int dim1, int dim2);
}; 
#endif // DWT_CDF_9_7_H

dwt_cdf_9_7.cpp

 #include <stdlib.h>
 #include "dwt_cdf_9_7.h"



 DWT_CDF_9_7::DWT_CDF_9_7(int width, int height, int steps)
{
this->width = width;
this->height = height;
this->steps = steps;
this->data = (int*) malloc(sizeof(int)*width*height);
}

int* DWT_CDF_9_7::forward(int block[], int blkptr) {
for (int i=0; i<this->steps; i++) {
    /* vertical transform */
   block = forward(block, blkptr, this->width, 1, this->width>>i, this->height>>i);

    /* horizontal transform */
   block = forward(block, blkptr, 1, this->width, this->height>>i, this->width>>i);
}

return block;
}

    int* DWT_CDF_9_7::forward(int block[], int blkptr, int stride, int inc, int dim1, int dim2) {
 {
   int stride2 = stride << 1;
   int endOffs = blkptr + (dim1 * inc);
   int half = stride * (dim2  >> 1);

   for (int offset=blkptr; offset<endOffs; offset+=inc)
   {
       int end = offset + (dim2 - 2) * stride;
       long tmp;
       int prev = block[offset];

       // First lifting stage : Predict 1
       for (int i=offset+stride; i<end; i+=stride2)
       {
           int next = block[i+stride];
           tmp = (PREDICT_1 * (prev + next));
           block[i] -= ((tmp + ADJUST) >> SHIFT);
           prev = next;
       }

       tmp = PREDICT_1 * block[end] ;
       block[end+stride] -= (((tmp + tmp) + ADJUST) >> SHIFT);
       prev = block[offset+stride];

       // Second lifting stage : Update 1
       for (int i=offset+stride2; i<=end; i+=stride2)
       {
           int next = block[i+stride];
           tmp = UPDATE_1 * (prev + next);
           block[i] -= ((tmp + ADJUST) >> SHIFT);
           prev = next;
       }

       tmp = UPDATE_1 * block[offset+stride];
       block[offset] -= (((tmp + tmp) + ADJUST) >> SHIFT);
       prev = block[offset];

       // Third lifting stage : Predict 2
       for (int i=offset+stride; i<end; i+=stride2)
       {
           int next = block[i+stride];
           tmp = PREDICT_2 * (prev + next);
           block[i] += ((tmp + ADJUST) >> SHIFT);
           prev = next;
       }

       tmp = PREDICT_2 * block[end];
       block[end+stride] += (((tmp + tmp) + ADJUST) >> SHIFT);
       prev = block[offset+stride];

       // Fourth lifting stage : Update 2
       for (int i=offset+stride2; i<=end; i+=stride2)
       {
           int next = block[i+stride];
           tmp = (UPDATE_2 * (prev + next));
           block[i] += ((tmp + ADJUST) >> SHIFT);
           prev = next;
       }

       tmp = UPDATE_2 * block[offset+stride];
       block[offset] += (((tmp + tmp) + ADJUST) >> SHIFT);

       // Scale
       for (int i=offset; i<=end; i+=stride2)
       {
           tmp = block[i] * SCALING_1;
           block[i] = (int) ((tmp + ADJUST) >> SHIFT);
           tmp = block[i+stride] * SCALING_2;
           block[i+stride] = (int) ((tmp + ADJUST) >> SHIFT);
       }

       // De-interleave sub-bands
       int endj = offset + half;

       for (int i=offset, j=offset; j<endj; i+=stride2, j+=stride)
       {
           this->data[j] = block[i];
           this->data[half+j] = block[i+stride];
       }

       block[end+stride] = this->data[end+stride];

       for (int i=offset; i<=end; i+=stride)
           block[i] = this->data[i];
   }

   return block;
 }
}
4

0 に答える 0