Generate gradient with CImg and dynamic array - c++

I'm trying to generate png with different resolution. But if i use dynamic array its generate only gray area. This is source of my code (C++ 16 bit grayscale gradient image from 2D array)
void generate_horizontal_gradient(char fileName[], int width, int height, int offset, bool direction)
{
unsigned short** buffer = new unsigned short* [height];
for (int i = 0; i < height; i++)
{
buffer[i] = new unsigned short[width];
}
for (int i = 0; i < height; i++)
{
unsigned short temp_data = 65535;
if (direction == true) {
for (int j = width; j > 0; j--)
{
buffer[i][j] = temp_data;
if (j < width - offset)
{
temp_data -= 65535 / (width - offset);
}
}
}
else
{
for (int j = 0; j < width; j++)
{
buffer[i][j] = temp_data;
if (j > offset)
{
temp_data -= 65535 / (width - offset);
}
}
}
}
auto hold_arr = (unsigned short*) &buffer[0][0];
cimg_library::CImg<unsigned short> img(hold_arr, width, height);
img.save_png(fileName);
}

Apparently I don’t understand something yet in two-dimensional arrays. Solved the problem through a one-dimensional array:
void generate_horizontal_gradient(char fileName[], int width, int height, int offset, bool direction)
{
unsigned short* buffer = new unsigned short[height * width];
//Add values to array.
for (int i = 0; i < height; i++)
{
unsigned short temp_data = 65535;
if (direction == true) {
for (int j = width; j > 0; j--)
{
buffer[i* width +j] = temp_data;
if (j < width - offset) temp_data -= 65535 / (width - offset);
}
}
else
{
for (int j = 0; j < width; j++)
{
buffer[i * width + j] = temp_data;
if (j > offset) temp_data -= 65535 / (width - offset);
}
}
}
unsigned short* hold_arr = (unsigned short*)& buffer[0*0];
cimg_library::CImg<unsigned short> img(buffer, width, height);
img.save_png(fileName);
}

Related

Problem in converting the "for loop" in CUDA

I have tried to extract patches from an image parallelly with pixel shift/overlapping. I have written the CPU version of the code. But I could not able to convert the for loop which has an increment of pixel shift. I have given the part of the code where for loop is being used. CreatePatchDataSet function has the "for loop " which has an increment of pixel shift. Please help me out to convert this function into Cuda. I have provided the following code.
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <fstream>
#include <sstream>
#include <random>
#include <vector>
#include <omp.h>
using namespace std;
using namespace cv;
#define PATCH_SIZE (5)
#define PIXEL_SHIFT (2)
void ConvertMat2DoubleArray(cv::Mat input, double* output)
{
for (int i = 0; i < input.rows; i++)
{
double *src = input.ptr<double>(i);
for (int j = 0; j < input.cols; j++)
{
output[input.cols * input.channels() * i + input.channels() * j + 0] = src[j];
}
}
}
void GetNumOfPatch(const int width, const int height, const int patch_size, const int pixel_shift, int* num_of_patch, int* num_of_patch_col, int* num_of_patch_row) {
*num_of_patch_col = 0;
int len_nb = 0;
while (len_nb < width) {
if (len_nb != 0) {
len_nb += patch_size - (patch_size - pixel_shift);
}
else {
len_nb += patch_size;
}
(*num_of_patch_col)++;
}
len_nb = 0;
*num_of_patch_row = 0;
while (len_nb < height) {
if (len_nb != 0) {
len_nb += patch_size - (patch_size - pixel_shift);
}
else {
len_nb += patch_size;
}
(*num_of_patch_row)++;
}
*num_of_patch = (*num_of_patch_col) * (*num_of_patch_row);
}
void CreatePatchDataSet(double *original_data, double* patch_data, const int width, const int height, const int pixel_shift, const int patch_size, const int num_of_patch_col, const int num_of_patch_row) {
int counter_row = 0;
int num_of_patch_image = num_of_patch_row * num_of_patch_col;
for (int i = 0; i < height; i += pixel_shift) {
int counter_col = 0;
for (int j = 0; j < width; j += pixel_shift) {
//Get Low Resolution Image
for (int ii = 0; ii < patch_size; ii++) {
for (int jj = 0; jj < patch_size; jj++) {
if ((i + ii) < height && (j + jj) < width) {
patch_data[num_of_patch_image * (patch_size * ii + jj) + num_of_patch_col*counter_row + counter_col] = original_data[width*(i + ii) + (j + jj)];
}
else {
patch_data[num_of_patch_image * (patch_size * ii + jj) + num_of_patch_col*counter_row + counter_col] = 0.;
}
}
}
counter_col++;
if (counter_col == num_of_patch_col) {
break;
}
}
counter_row++;
if (counter_row == num_of_patch_row) {
break;
}
}
}
int main()
{
int ratio=2;
cv::Mat image = cv::imread("input_b2_128.tif", CV_LOAD_IMAGE_UNCHANGED);
cv::Mat imageH = cv::Mat(image.rows * ratio, image.cols * ratio, CV_8UC1);
cv::resize(image, imageH, cv::Size(imageH.cols, imageH.rows), 0, 0,
cv::INTER_LANCZOS4);
double* orgimageH = (double*)calloc(imageH.cols*imageH.rows*image.channels(), sizeof(double));
ConvertMat2DoubleArray(imageH, orgimageH);
int widthH = imageH.cols;
int heightH = imageH.rows;
int dimH = (int)PATCH_SIZE * (int)PATCH_SIZE* (int)image.channels();
int dimL = (int)PATCH_SIZE/ratio* (int)PATCH_SIZE/ratio * (int)image.channels();
//3. Create training data set=========================
int num_of_patch_image = 0;
int num_of_patch_col = 0;
int num_of_patch_row = 0;
GetNumOfPatch(widthH, heightH, (int)PATCH_SIZE, (int)PIXEL_SHIFT, &num_of_patch_image, &num_of_patch_col, &num_of_patch_row);
cout<<"patch numbers: \n " << num_of_patch_image << endl;
double* FY = (double*)calloc(dimH * num_of_patch_image, sizeof(double));
CreatePatchDataSet(orgimageH, FY, widthH, heightH, (int)PIXEL_SHIFT, (int)PATCH_SIZE, num_of_patch_col, num_of_patch_row);
free(orgimageH);
free(FY);
return 0;
}
The results I got for first 10 values in CPU version:
patch numbers:
16129
238,240,240,235,237,230,227,229,228,227
I have tried to convert this function to Kernel function using cuda:. But it goes into the infinite loop. As I am very new to this CUDA field, could you please help me to find out the problem in the code ?
__global__ void CreatePatchDataSet(double *original_data, double* patch_data, const int width, const int height, const int pixel_shift, const int patch_size, const int num_of_patch_col, const int num_of_patch_row) {
int num_of_patch_image = num_of_patch_row * num_of_patch_col;
int i = threadIdx.x + (blockDim.x*blockIdx.x);
int j = threadIdx.y + (blockDim.y*blockIdx.y);
while (i<height && j< width)
{
int counter_row = 0;
int counter_col = 0;
//Get Low Resolution Image
for (int ii = 0; ii < patch_size; ii++) {
for (int jj = 0; jj < patch_size; jj++) {
if ((i + ii) < height && (j + jj) < width) {
patch_data[num_of_patch_image * (patch_size * ii + jj) + num_of_patch_col*counter_row + counter_col] = original_data[width*(i + ii) + (j + jj)];
}
else {
patch_data[num_of_patch_image * (patch_size * ii + jj) + num_of_patch_col*counter_row + counter_col] = 0.;
}
}
}
counter_col++;
if (counter_col == num_of_patch_col) {
break;
}
counter_row++;
if (counter_row == num_of_patch_row) {
break;
}
}
i+= blockDim.x*gridDim.x;
j+= blockDim.y*gridDim.y;
}
int main()
{
int ratio=2;
cv::Mat image = cv::imread("input_b2_128.tif", CV_LOAD_IMAGE_UNCHANGED);
cv::Mat imageH = cv::Mat(image.rows * ratio, image.cols * ratio, CV_8UC1);
cv::resize(image, imageH, cv::Size(imageH.cols, imageH.rows), 0, 0, cv::INTER_LANCZOS4);
double *orgimageH = (double*)calloc(imageH.cols*imageH.rows*image.channels(), sizeof(double));
ConvertMat2DoubleArray(imageH, orgimageH);
int widthH = imageH.cols;
int heightH = imageH.rows;
//
int dimH = (int)PATCH_SIZE * (int)PATCH_SIZE* (int)image.channels();
int dimL = (int)PATCH_SIZE/ratio* (int)PATCH_SIZE/ratio * (int)image.channels();
//3. Create training data set=========================
int num_of_patch_image = 0;
int num_of_patch_col = 0;
int num_of_patch_row = 0;
GetNumOfPatch(widthH, heightH, (int)PATCH_SIZE, (int)PIXEL_SHIFT, &num_of_patch_image, &num_of_patch_col, &num_of_patch_row);
cout<<"patch numbers: \n " << num_of_patch_image << endl;
double* FY = (double*)calloc(dimH * num_of_patch_image, sizeof(double));
double *d_orgimageH;
gpuErrchk(cudaMalloc ((void**)&d_orgimageH, sizeof(double)*widthH*heightH));
double *d_FY;
gpuErrchk(cudaMalloc ((void**)&d_FY, sizeof(double)* dimH * num_of_patch_image));
gpuErrchk(cudaMemcpy(d_orgimageH , orgimageH , sizeof(double)*widthH*heightH, cudaMemcpyHostToDevice));
dim3 dimBlock(16, 16);
dim3 dimGrid;
dimGrid.x = (widthH + dimBlock.x - 1) / dimBlock.x;
dimGrid.y = (heightH + dimBlock.y - 1) / dimBlock.y;
CreatePatchDataSet<<<dimGrid,dimBlock>>>(d_orgimageH, d_FY, widthH, heightH, (int)PIXEL_SHIFT, (int)PATCH_SIZE, num_of_patch_col, num_of_patch_row);
gpuErrchk(cudaMemcpy(FY,d_FY, sizeof(double)*dimH * num_of_patch_image, cudaMemcpyDeviceToHost));
// cout<<"Hello world";
free(orgimageH);
free(FY);
cudaFree(d_FY);
cudaFree(d_orgimageH);
return 0;
}
Image I have used: [1]: https://i.stack.imgur.com/Ywg7p.png
i+= blockDim.x*gridDim.x;
j+= blockDim.y*gridDim.y;
is outside the while loop in your kernel. As i and j never change inside the while loop, it isn't stopping. There could be more problems here, but this is the most prominent one.
EDIT: Another one that I found, is that you have only one while over both i and j instead of one for each. You should probably use for loops like in your CPU code:
for (i = pixel_shift * (threadIdx.x + (blockDim.x*blockIdx.x));
i < height;
i += pixel_shift * blockDim.x * gridDim.x) {
for (j = ...; j < ...; j += ...) {
/* ... */
}
}
EDIT 2:
I could imagine this to be a good idea:
for (counter_row = threadIdx.y + blockDim.y * blockIdx.y;
counter_row < num_of_patch_row;
counter_row += blockDim.y * gridDim.y) {
i = counter_row * pixel_shift;
if (i > height)
break;
for (counter_col = threadIdx.x + blockDim.x * blockIdx.x;
counter_col < num_of_patch_col;
counter_col += blockDim.x * gridDim.x) {
j = counter_col * pixel_shift;
if (j > width)
break;
/* ... */
}
}
I have also exchanged the x/y fields of the execution parameters between the inner and the outer loop, as it seemed more appropriate considering that the x field is continuous in warps (memory access benefits).

Gaussian filter reads same value multiple time usin BMP image

I need to translate GaussianFilter that uses openCV to code that uses BMP image ( so i first read image, and translate it to greyscale). My function using openCV looks like ( basic GaussianFilter ) :
Mat CreateGaussFilter(int kernalHeight, int kernalWidth, double kernalArray[5][5]){
Mat image = imread("konik.jpg");
Mat grayScaleImage(image.size(),CV_8UC1);
Mat filter(image.size(),CV_8UC1);
cvtColor(image,grayScaleImage,CV_RGB2GRAY);
int rows=image.rows;
int cols=image.cols;
int verticleImageBound=(kernalHeight-1)/2;
int horizontalImageBound=(kernalWidth-1)/2;
for(int row=0+verticleImageBound;row<rows-verticleImageBound;row++){
for(int col=0+horizontalImageBound;col<cols-horizontalImageBound;col++){
float value=0.0;
for(int kRow=0;kRow<kernalHeight;kRow++){
for(int kCol=0;kCol<kernalWidth;kCol++){
float pixel=grayScaleImage.at<uchar>(kRow+row-verticleImageBound,kCol+col-horizontalImageBound)*kernalArray[kRow][kCol];
value+=pixel;
}
}
filter.at<uchar>(row,col)=cvRound(value);
}
}
return filter;
}
Now for BMP image:
i have loaded it using:
struct Info{
int width;
int height;
int offset;
unsigned char * info;
unsigned char * data;
int size;
};
Info readBMP(char* filename)
{
int i;
std::ifstream is(filename, std::ifstream::binary);
is.seekg(0, is.end);
i = is.tellg();
is.seekg(0);
unsigned char *info = new unsigned char[i];
is.read((char *)info,i);
int width = *(int*)&info[18];
int height = *(int*)&info[22];
int offset = *(int*)&info[10];
unsigned char a[offset];
unsigned char *b = new unsigned char[i - offset];
std::copy(info,
info + offset,
a);
std::copy(info + offset,
info + i,
b + 0);
Info dat;
dat.width = width;
dat.height = height;
dat.offset = offset;
dat.size = i;
dat.info = new unsigned char[offset - 1];
dat.data = new unsigned char[i - offset + 1];
for( int j = 0; j < offset ; j++ ){
dat.info[j] = a[j];
}
for( int j = 0; j < i - offset; j++ ){
dat.data[j] = b[j];
}
return dat;
}
turned it into grayscale usin:
void greyScale( unsigned char * src , int rows, int cols){
for( int i = 0; i < rows; i++){
for( int j = 0; j < cols; j++){
unsigned char r = src[3 * (i * cols + j)];
unsigned char g = src[3 * (i * cols + j) + 1];
unsigned char b = src[3 * (i * cols + j) + 2];
char linearIntensity = (char)(0.2126f * r + 0.7512f * g + 0);
src[3 * (i * cols + j)] = linearIntensity;
src[3 * (i * cols + j) + 1] = linearIntensity;
src[3 * (i * cols + j) + 2] = linearIntensity;
}
}
}
And now i am trying to use GaussianFilter ( translated from my OpenCV function )
void FilterCreation(double GKernel[][5]) {
// intialising standard deviation to 1.0
double sigma = 1.0;
double r, s = 2.0 * sigma * sigma;
// sum is for normalization
double sum = 0.0;
// generating 5x5 kernel
for (int x = -2; x <= 2; x++) {
for (int y = -2; y <= 2; y++) {
r = sqrt(x * x + y * y);
GKernel[x + 2][y + 2] = (exp(-(r * r) / s)) / (M_PI * s);
sum += GKernel[x + 2][y + 2];
}
}
// normalising the Kernel
for (int i = 0; i < 5; ++i)
for (int j = 0; j < 5; ++j)
GKernel[i][j] /= sum;
}
unsigned char ** CreateGaussFilter(unsigned char ** src,int kernalHeight, int kernalWidth, double kernalArray[5][5], int rows, int cols){
int verticleImageBound=(kernalHeight-1)/2;
int horizontalImageBound=(kernalWidth-1)/2;
unsigned char ** dst = new unsigned char *[rows];
for( int i = 0; i < rows; i++){
dst[i] = new unsigned char [cols];
}
for(int row=0+verticleImageBound;row<rows-verticleImageBound;row++){
for(int col=0+horizontalImageBound;col<cols-horizontalImageBound;col++){
float value=0;
for(int kRow=0;kRow<kernalHeight;kRow++){
for(int kCol=0;kCol<kernalWidth;kCol++){
float pixel =src[kRow+row-verticleImageBound][kCol+col-horizontalImageBound]*kernalArray[kRow][kCol];
value+=pixel;
}
}
dst[row][col] = round(value);
}
}
return dst;
}
Since grayscale values are same for every channel, istead of doing calculation like in grayscale function, i turned the data into 2d array and then back into 1d array using:
unsigned char ** return2darray(unsigned char *src, int width, int height, int size){
unsigned char **array = new unsigned char *[width];
for( int i = 0; i < width; i++ ){
array[i] = new unsigned char[height];
}
for( int i = 0; i < width; i++ ){
for( int j = 0; j < height; j++ ){
array[i][j] = src[3 * (i * height + j)];
}
}
return array;
}
unsigned char * return1darray(unsigned char **src, int width, int height, int size){
unsigned char *array = new unsigned char[size];
for( int i = 0; i < width; i++ ){
for( int j = 0; j < height; j++ ){
array[3 * (i * height + j)] = src[i][j];
array[3 * (i * height + j) + 1] = src[i][j];
array[3 * (i * height + j) + 2] = src[i][j];
}
}
return array;
}
And using it like:
int main() {
// load img
Info dat = readBMP("input.bmp");
// turn in into greyscale
greyScale(dat.data,dat.width,dat.height);
// turn 1d array into 2d
unsigned char** arr = return2darray(dat.data,dat.width,dat.height,dat.size);
double GKernel[5][5];
// geneate gausian filter
FilterCreation(GKernel);
// apply gausianFilter
unsigned char** filter = CreateGaussFilter(arr,5,5,GKernel,dat.width,dat.height,dat.size);
// convert it back into 1d array
unsigned char* ar = return1darray(filter,dat.width,dat.height,dat.size);
ofstream fout;
fout.open("out.bmp", ios::binary | ios::out);
fout.write( reinterpret_cast<char *>(dat.info), dat.offset);
fout.write( reinterpret_cast<char *>(ar), dat.size - dat.offset );
fout.close();
return 0;
}
But for some reason, that I cannot realize for input :
the output looks like this.
It seems like it reads the same values in periodes, but that would mean the original image would have the same periods because it just reads bytes from loaded image. The GreyScale function works as it should. I am not very proficient in manipulation with images ( i was using openCV all the time ) What could cause these periods? Thanks for the help!

Access violation when reading 2d array C++

My code seems to have a bug somewhere but I just can't catch it. I'm passing a 2d array to three sequential functions. First function populates it, second function modifies the values to 1's and 0's, the third function counts the 1's and 0's. I can access the array easily inside the first two functions, but I get an access violation at the first iteration of the third one.
Main
text_image_data = new int*[img_height];
for (i = 0; i < img_height; i++) {
text_image_data[i] = new int[img_width];
}
cav_length = new int[numb_of_files];
// Start processing - load each image and find max cavity length
for (proc = 0; proc < numb_of_files; proc++)
{
readImage(filles[proc], text_image_data, img_height, img_width);
threshold = makeBinary(text_image_data, img_height, img_width);
cav_length[proc] = measureCavity(bullet[0], img_width, bullet[1], img_height, text_image_data);
}
Functions
int makeBinary(int** img, int height, int width)
{
int threshold = 0;
unsigned long int sum = 0;
for (int k = 0; k < width; k++)
{
sum = sum + img[1][k] + img[2][k] + img[3][k] + img[4][k] + img[5][k];
}
threshold = sum / (width * 5);
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
img[i][j] = img[i][j] > threshold ? 1 : 0;
}
}
return threshold;
}
// Count pixels - find length of cavity here
int measureCavity(int &x, int& width, int &y, int &height, int **img)
{
double mean = 1.;
int maxcount = 0;
int pxcount = 0;
int i = x - 1;
int j;
int pxsum = 0;
for (j = 0; j < height - 2; j++)
{
while (mean > 0.0)
{
for (int ii = i; ii > i - 4; ii--)
{
pxsum = pxsum + img[ii][j] + img[ii][j + 1];
}
mean = pxsum / 4.;
pxcount += 2;
i += 2;
pxsum = 0;
}
maxcount = std::max(maxcount, pxcount);
pxcount = 0;
j++;
}
return maxcount;
}
I keep getting an access violation in the measureCavity() function. I'm passing and accessing the array text_image_data the same way as in makeBinary() and readImage(), and it works just fine for those functions. The size is [550][70], I'm getting the error when trying to access [327][0].
Is there a better, more reliable way to pass this array between the functions?

Copying R8G8B8A8 image to R8G8B8

I'm trying to convert an R8G8B8A8 image to R8G8B8 image, what I get right now is an image, but with a lot of scan lines, I have byters per pixels is 4 bytes, 32bit.
The image buffer is of type unsigned char [width*height*4] that's the source and the destination is unsigned char [width*height*3].
int j = 0;
int i = 0;
for (int k = 0; k < (width*height); k++)
{
for(int b = 0; b < 3; b++)
{
dst[i + b] = src[j + b];
}
i+=3;
j+=4;
}
Probably the destination image requires lines aligned on a 4 bytes boundary:
for(unsigned int y(0); y != height; ++y)
{
unsigned int sourceStart(y * width * 4);
unsigned int destStart(y * ((width * 3 + 3) & 0xfffffffc) ); // align on 4 bytes
for(unsigned int x(0); x != width; ++x)
{
for(unsigned int color(0); color != 3; ++color)
{
dst[destStart++] = src[sourceStart++];
}
++sourceStart; // account for 4th byte in source
}
}
You can do this:
for (int k = 0; k < width*height; k++)
{
for(int b = 0; b < 3; b++)
{
dst[k*3 + b] = src[k*4 + b];
}
}

Image denoising using 2d Haar wavelet transform by soft-thresholding (C++)

I am trying to implement one of the basic 2D wavelet transform by Haar transformation.
I applied this to the image denoising problem.
My restored result has some black blocks and somw white blocks.
I guess I stuck on the part of soft-thresholding without normalizing.
Here is my Code :
#include "StdAfx.h"
#include "WaveletDenoising.h"
#include <cmath>
WaveletDenoising::WaveletDenoising(void)
{
}
WaveletDenoising::~WaveletDenoising(void)
{
}
/* Forward Haar wavelet transform: */
void WaveletDenoising::ForwardHaar1D(double* data, int length)
{
const float inv_sqrt2 = 1/sqrt((double)2.0);
float norm = 1.0f/sqrt((double)length);
for(int i=0; i < length; i++) {
data[i] *= norm;
}
float *tmp = new float[length];
while(length > 1) {
length /= 2;
for(int i=0; i < length; i++) {
tmp[i] = (data[2*i] + data[2*i+1]) * inv_sqrt2;
tmp[length + i] = (data[2*i] - data[2*i+1]) * inv_sqrt2;
}
memcpy(data, tmp, length*2*sizeof(float));
}
delete [] tmp;
}
/* Transpose matrix: */
void WaveletDenoising::Transpose(double *data, int width, int height)
{
double *B = new double[width*height];
for(int y=0; y < height; y++) {
for(int x=0; x < width; x++) {
B[x*height + y] = data[y*width + x];
}
}
memcpy(data, B, sizeof(double)*width*height);
delete [] B;
}
/* Forward 2d Haar wavelet transform: */
void WaveletDenoising::ForwardHaar2D(double* data, int width, int height)
{
for(int i=0; i < height; i++)
ForwardHaar1D(&data[i*width], width);
Transpose(data, width, height);
for(int i=0; i < width; i++)
ForwardHaar1D(&data[i*height], height);
Transpose(data, height, width);
}
/* Inverse 1d Haar transform */
void WaveletDenoising::InverseHaar1D(double* data, int length)
{
const float inv_sqrt2 = 1/sqrt((double)2.0);
float inv_norm = sqrt((double)length);
float *tmp = new float[length];
int k = 1;
while(k < length) {
for(int i=0; i < k; i++) {
tmp[2*i] = (data[i] + data[k+i]) * inv_sqrt2;
tmp[2*i+1] = (data[i] - data[k+i]) * inv_sqrt2;
}
memcpy(data, tmp, sizeof(double)*(k*2));
k *= 2;
}
for(int i=0; i < length; i++) {
data[i] *= inv_norm;
}
delete [] tmp;
}
/* Inverse 2d Haar wavelet transform */
void WaveletDenoising::InverseHaar2D(double* data, int width, int height)
{
for(int i=0; i < width; i++) {
InverseHaar1D(&data[i*height], height);
}
Transpose(data, height, width);
for(int i=0; i < height; i++) {
InverseHaar1D(&data[i*width], width);
}
Transpose(data, width, height);
}
/* Image denoising by soft-thresholding */
void WaveletDenoising::WaveletThresholdDenoising(int width, int height, double* src, double* des, double threshold)
{
int i, j, x, y;
this->ForwardHaar2D(src, width, height);
double mi = src[0*width+0]; /* find min value */
double ma = src[0*width+0]; /* find max value */
for (y=0; y<height; y++)
{
for (x=0; x<width; x++)
{
if (mi > src[y*width+x])
mi = src[y*width+x];
if (ma < src[y*width+x])
ma = src[y*width+x];
}
}
/* soft-thresholding */
for (y=0; y<height; y++)
{
for (x=0; x<width; x++)
{
if (src[y*width+x] < threshold)
src[y*width+x] = 0;
else if (src[y*width+x] > threshold)
src[y*width+x] = src[y*width+x] - threshold;
else if (src[y*width+x] < -threshold)
src[y*width+x] = src[y*width+x] + threshold;
}
}
this->InverseHaar2D(src, width, height);
for (y=0; y<height; y++)
{
for (x=0; x<width; x++)
{
// for normalized:
src[y*width+x] = ((src[y*width+x] - mi) / (ma - mi))*255;
double temp = src[y*width+x];
if (temp < 0) temp = 0;
else if (temp >255) temp = 255;
else temp = temp;
des[y*width+x] = (BYTE) src[y*width+x];
}
}
}
How can i do this ?
After spending some hours on this code, I finally found the problem of my code. First, I had to change double type instead of float of the temp variable in InverseHaar1D function. Second, adjust the threshold value in the calling function depending on the degree of noise level. Third, get rid of some redundancy lines as the following clear function. You can see the result with this link: https://www.mediafire.com/?v80rslisl7fff6n
/* Image denoising by soft-thresholding */
void WaveletDenoising::WaveletThresholdDenoising(int width, int height, double* src, double* des, double threshold)
{
int x, y;
/* Forward 2d Haar transform */
this->ForwardHaar2D(src, width, height);
/* soft-thresholding */
for(y=0; y < height; y++)
{
for(x=0; x < width; x++)
{
if (src[y*width+x] > threshold)
src[y*width+x] = src[y*width+x] - threshold;
else if (src[y*width+x] < -threshold)
src[y*width+x] = src[y*width+x] + threshold;
else
src[y*width+x] = 0;
}
}
/* Inverse 2D Haar transform */
this->InverseHaar2D(src, width, height);
for (y=0; y<height; y++)
{
for (x=0; x<width; x++)
{
double temp = src[y*width+x];
if (temp < 0) temp = 0;
else if (temp >255) temp = 255;
else
des[y*width+x] = (BYTE) temp;
}
}
}