freeimage边缘检测

来源:互联网 发布:mac 安装wget命令 编辑:程序博客网 时间:2024/04/30 10:46

项目地址:https://github.com/buleks/MPI-image-edges-detection

edges.h文件

#ifndef EDGES_H
#define EDGES_H
#include <string>
#include <iostream>
#include <FreeImage.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include <mpi.h>


class Image 
{
FIBITMAP *bitmap;
FIBITMAP *edge;

unsigned int bpp;
int scan_width;


uint8_t *bitmappixels;
int world_size;

public:

Image()
{
FreeImage_Initialise();
}


std::string inputFileName;
static constexpr int32_t conv[9] = {0,1,0,1,-4,1,0,1,0};
//static constexpr int32_t conv[9] = {0,0,0,1,-1,0,0,0,0};
int w,h;

struct fragment_info {
int width;
int rows;
int bufferStart;
int bufferlength;
bool first;
bool last;
};

struct imageBlock_info 
{
int start;
int size;
};


Image(int world_size): world_size(world_size)
{

}

imageBlock_info getBlockinfo(int rank)
{
imageBlock_info block;
if(rank == 0)
{
block.start = 0;
}
else
{
block.start = rank*w-h; //because it must have one line more before to calculations
}

}

fragment_info process_info[10]; // assumes max 10 processes

fragment_info* divideImage()
{
//calculate width and height for each row
int rem = h  % world_size;
if(rem == 0)
{
int rowsperprocess = h/world_size;
for(int i =0; i < world_size;i++)
{
process_info[i].width = w;
process_info[i].rows = rowsperprocess;

}
}
else
{
int rowsperprocess = h/world_size;
for(int i =0; i < world_size-1;i++)
{
process_info[i].width = w;
process_info[i].rows = rowsperprocess;
}
process_info[world_size-1].width = w;
process_info[world_size-1].rows = h-(world_size-1)*rowsperprocess;

}


///fill buffer info
int previousRawBufferStart =0;
int previousRawBufferLength =0;

process_info[0].bufferStart = 0;
previousRawBufferLength = process_info[0].width*(process_info[0].rows);
process_info[0].bufferlength = previousRawBufferLength+process_info[0].width;//needs one row more to claculate filtered values
process_info[0].first = true;
process_info[0].last = false;

for(int i =1; i < world_size;i++)
{

previousRawBufferStart = process_info[i].bufferStart = previousRawBufferStart+previousRawBufferLength;
process_info[i].bufferStart -= w; //one line before
previousRawBufferLength = process_info[i].width*(process_info[i].rows);
process_info[i].bufferlength = previousRawBufferLength+w; //one more because one line before
if(i != world_size - 1) //if not last
{
process_info[i].bufferlength  +=w;//one line more after
process_info[i].first = false;
process_info[i].last = false;
}
if(i == world_size - 1) //if last
{
process_info[i].first = false;
process_info[i].last = true;
}

}
return process_info;
}


void printprocessinfo()
{
for(int i =0; i < world_size;i++)
{
std::cout<<"[List]Rank"<<i<<" rows:"<<process_info[i].rows<<" Start:"<<process_info[i].bufferStart<<" length"<<process_info[i].bufferlength<<std::endl;
}
}

bool readfile(std::string img_filename)
{
FREE_IMAGE_FORMAT format;
inputFileName = img_filename;
format = FreeImage_GetFileType(img_filename.c_str());
if(format == FIF_UNKNOWN )
{
std::cout<<"File: "<<img_filename<<" unknown format"<<std::endl;
return false;
}


bitmap = FreeImage_Load(format,img_filename.c_str(),BMP_DEFAULT);
if(!bitmap)
{
std::cout<<"Cannot open image file:"<<img_filename<<std::endl;
return false;
}


w = FreeImage_GetWidth(bitmap);
h = FreeImage_GetHeight(bitmap);
bpp = FreeImage_GetBPP(bitmap);
scan_width = FreeImage_GetPitch(bitmap);
std::cout<<"Width:"<<w<<"Height"<<h<<std::endl;
std::cout<<"Bpp:"<<bpp<<std::endl;
std::cout<<"Pitch:"<<scan_width<<std::endl;

FIBITMAP *old_bitmap = bitmap;
bitmap = FreeImage_ConvertToGreyscale(bitmap);
bitmappixels = (uint8_t*)FreeImage_GetBits(bitmap);
FreeImage_Unload(old_bitmap);
return true;
}

uint8_t* getsourcebuffer()
{

return bitmappixels;
}

~Image()
{
FreeImage_Unload(bitmap);
FreeImage_DeInitialise();
}
};


#endif


edges.cpp文件:

#include "edges.h"
#include <mpi.h>
#include <sstream>
#include <chrono>




using namespace std;
using namespace std::chrono;


constexpr int INFO_TAG = 13;
constexpr int DATA_TAG = 14;
constexpr int RESULT_TAG = 15;
constexpr uint8_t THRESHOLD = 30;


int main(int argc,char **argv)
{
int size,rank;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&size);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
//cout<<"World size:"<<size<<endl;
cout<<"WRank:"<<rank<<endl;

MPI_Datatype ProcessDataInfo;
MPI_Datatype types[6] = { MPI_INT, MPI_INT, MPI_INT,MPI_INT,MPI::BOOL,MPI::BOOL };
MPI_Aint     offsets[6];
int blocklengths[6] = { 1, 1, 1,1,1,1 };
offsets[0] = offsetof(Image::fragment_info,width);
offsets[1] = offsetof(Image::fragment_info,rows);
offsets[2] = offsetof(Image::fragment_info,bufferStart);
offsets[3] = offsetof(Image::fragment_info,bufferlength);
offsets[4] = offsetof(Image::fragment_info,first);
offsets[5] = offsetof(Image::fragment_info,last);

MPI_Type_create_struct(6, blocklengths, offsets, types, &ProcessDataInfo);
MPI_Type_commit(&ProcessDataInfo);

int imageSize=0;
Image *img;
Image::fragment_info *dataInfo;
uint8_t treshold = THRESHOLD ;
if(argc == 3)
{
treshold = atoi(argv[2]);
}

high_resolution_clock::time_point t1;
high_resolution_clock::time_point t2;
if(rank == 0)
{
if(argc < 2)
{
cout<<"Needs file name as argument. Optionally threshold(range 0-255). For example ./edge 1.jpg 10\n";
exit(1);
}

img = new Image(size);
string inputFileName = argv[1];
img->readfile(inputFileName);

t1 = high_resolution_clock::now();

imageSize = img->w*img->h;
dataInfo = img->divideImage();
img->printprocessinfo();



for(int i = 1; i < size;i++)
{
MPI_Send(&dataInfo[i],1,ProcessDataInfo,i,INFO_TAG,MPI_COMM_WORLD);
}

uint8_t *image = img->getsourcebuffer();
for(int i = 1; i < size;i++)
{
MPI_Send(&image[dataInfo[i].bufferStart], dataInfo[i].bufferlength, MPI_UINT8_T,i,DATA_TAG,MPI_COMM_WORLD);
}

}

Image::fragment_info processDatainfo;
MPI_Status status;
if(rank != 0)
{
MPI_Recv(&processDatainfo,1,ProcessDataInfo,0,INFO_TAG,MPI_COMM_WORLD,&status);
}else
{
processDatainfo = dataInfo[0];
}
cout<<"Rank"<<rank<<" rows:"<<processDatainfo.rows<<" start:"<<processDatainfo.bufferStart<<" length:"<< processDatainfo.bufferlength<<" first:"<<processDatainfo.first<<" last:"<<processDatainfo.last<<std::endl;
uint8_t *imagePart = new uint8_t[processDatainfo.bufferlength];


if(rank == 0)
{
uint8_t *temp = img->getsourcebuffer();
memcpy(imagePart,temp,processDatainfo.bufferlength);
}
else
{
MPI_Recv(imagePart,processDatainfo.bufferlength,MPI_UINT8_T,0,DATA_TAG,MPI_COMM_WORLD,&status);
cout<<"Received image fragment"<<endl;
}



int w = processDatainfo.width;
int partImageSize = processDatainfo.width*processDatainfo.rows;

uint8_t *processImagePart = new uint8_t[partImageSize];



for(int i =0 ; i < partImageSize;i++)
{

//if(i%w == 0) //first column
//((i%w == 0) ?  : 0)

//(((i-1)%w == 0) ? 0 : ) //last column

int32_t temp=0;
////calculations based on first line of coefficients matrix
if(true == processDatainfo.first )//first fragment
{
//first line of coefficients matrix shouldnt be calculated
if(i >= w)
{
temp+=Image::conv[0]*(((i-1-w) >=0) ? imagePart[i-1-w] : 0);
temp+=Image::conv[1]*imagePart[i-w];
temp+=Image::conv[2]*(((i-1-w)%w == 0) ? 0 : imagePart[i+1-w]);
}
} else
{//(((i-1) >=0) ?  : 0)
temp+=Image::conv[0]*(((i-1) >=0) ? imagePart[i-1] : 0);
temp+=Image::conv[1]*imagePart[i];
temp+=Image::conv[2]*(((i-1)%w == 0) ? 0 : imagePart[i+1]);
}
////end of first line of coefficients matrix

////calculations based on second line of coefficients matrix
if(true == processDatainfo.first )//first fragment
{
temp+=Image::conv[3]*((i%w == 0) ? 0 : imagePart[i-1]);
temp+=Image::conv[4]*imagePart[i];
temp+=Image::conv[5]*(((i-1)%w == 0) ? 0 : imagePart[i+1]);
}
else
{
temp+=Image::conv[3]*((i%w == 0) ? 0 : imagePart[i+w-1]);
temp+=Image::conv[4]*imagePart[i+w];
temp+=Image::conv[5]*(((i-1)%w == 0) ? 0 : imagePart[i+w+1]);
}

////end of calculations based on first line of coefficients matrix


//third line of matrix
if(true == processDatainfo.first )//first fragment
{
temp+=Image::conv[6]*((i%w == 0) ? 0 : imagePart[i+w-1]);
temp+=Image::conv[7]*imagePart[i+w];
temp+=Image::conv[8]*(((i-1)%w == 0) ? 0 : imagePart[i+w+1]);
}else
{
//if(!(true == processDatainfo.last && i>= (partImageSize-w))) //all lines without last line in last fragment
{
temp+=Image::conv[6]*((i%w == 0) ? 0 : imagePart[i+2*w-1]);
temp+=Image::conv[7]*imagePart[i+2*w];
temp+=Image::conv[8]*(((i-1)%w == 0) ? 0 : imagePart[i+2*w+1]);
}

}


////////////////
//copy raw image into image part
//if(true == processDatainfo.first )
//{
// processImagePart[i]=imagePart[i];
//}else
//{
// processImagePart[i]=imagePart[i+w];
//}
//end raw image
////////
if(temp>treshold)
{
processImagePart[i]=0xff;
}
else
{
processImagePart[i]=0;
}

}




delete imagePart;


int *receiveCounts = new int[size];
int *displacement = new int[size];
if(rank == 0)
{
displacement[0]=0;
for(int i=0;i < size; i++)
{
receiveCounts[i] = dataInfo[i].width*dataInfo[i].rows;
if(i>0)
{
displacement[i]= displacement[i-1]+receiveCounts[i-1];
}
}
}

FIBITMAP *edge = FreeImage_Allocate(img->w, img->h, 8);
uint8_t *gatheredImage = (uint8_t *)FreeImage_GetBits(edge);

MPI_Gatherv(processImagePart, partImageSize,MPI_UINT8_T,gatheredImage, receiveCounts, displacement, MPI_UINT8_T,0, MPI_COMM_WORLD);
if(rank == 0)
{
cout<<"Received gathered data"<<endl;
}
delete processImagePart; //remove process image buffer
t2 = high_resolution_clock::now();

if(rank == 0)
{
std::ostringstream file;
file << "e_"<<img->inputFileName;
FreeImage_Save(FIF_PNG,edge,file.str().c_str(),0);
FreeImage_Unload(edge);
delete img;
auto duration = duration_cast<microseconds>( t2 - t1 ).count();
cout <<"Execution time"<< duration/1000<<" ms"<<endl;
}
MPI_Type_free(&ProcessDataInfo);
MPI_Finalize();
return 0;
}

0 0
原创粉丝点击