Фильтр Гаусса, обработка изображения с помощью процессов и потоков
Доброго времени суток, уважаемые программисты!
Есть проблемка. Дано изображение, которое будет обрабатываться фильтром Гаусса, код обработки есть, все прекрасно работает, НО препод для проверки дает картинку 20000x20000 пикселей, и, естественно, моим проходом это будет обрабатываться очень долго. И он сказал, что если поделить картинку на несколько частей и обработать с помощью процессов и потоков, то все должно пройти немного быстрее. В связи с этим, не имея литературы, прошу помощи у тех, кто сталкивался с подобной проблемой или знает, как разбить это все на потоки.
Код программы выкладываю для проверки работоспособности и внесения возможных поправок. Реализация программы в QT Creator 5.
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
ui->label->clear();
ui->label_2->clear();
}
void MainWindow::on_pushButton_clicked()
{
QFileDialog *dlg;
dlg=new QFileDialog;
FName=dlg->getOpenFileName();
delete dlg;
old_image.load(FName);
new_image=new QImage(old_image.width(),old_image.height(),QImage::Format_RGB32);
ui->label->setPixmap(QPixmap::fromImage(old_image));
create_gauss(core_h,core_w,sigma);
float*** tmp=new float**[old_image.height()+(core_h-1)];
for (int i=0;i<old_image.height()+(core_h-1);i++)
{ tmp[i]=new float*[old_image.width()+(core_w-1)];
for (int j=0;j<old_image.width()+(core_w-1);j++)
{ tmp[i][j]=new float[3];
}
}
cpy_img_from_tmp(tmp,core_h,core_w,old_image.height()+(core_h-1),old_image.width()+(core_w-1));
float*** for_saving=new float**[old_image.height()+(core_h-1)];
for (int i=0;i<old_image.height()+(core_h-1);i++)
{ for_saving[i]=new float*[old_image.width()+(core_w-1)];
for (int j=0;j<old_image.width()+(core_w-1);j++)
{ for_saving[i][j]=new float[3];
}
}
gauss_filter(tmp,for_saving,core_g,core_h,core_w,old_image.height()+(core_h-1),old_image.width()+(core_w-1));
normalize(for_saving,old_image.height()+(core_h-1),old_image.width()+(core_w-1));
for (int i=0;i<old_image.height();i++)
for (int j=0;j<old_image.width();j++)
{
new_image->setPixel(j,i,qRgb(for_saving[i+core_h/2][j+core_w/2][0],for_saving[i+core_h/2][j+core_w/2][1],for_saving[i+core_h/2][j+core_w/2][2]));
}
ui->label_2->setPixmap(QPixmap::fromImage(*new_image));
new_image->save("new","jpg");
qDebug() << "Finished!";
}
void MainWindow::create_gauss(int core_h, int core_w, float sigma)
{
core_g = new float *[core_h];
for (int i=0;i<core_h;i++)
{
core_g[i] = new float [core_w];
}
for (int i=0;i<core_h;i++)
{
for (int j=0;j<core_w;j++)
{
core_g[i][j]=gauss_matrix(i-((core_h-1)/2),j-((core_w-1)/2),sigma);
}
}
}
float MainWindow::gauss_matrix(float x,float y,float sigma)
{
return (1/(2*M_PI*sigma*sigma)*exp(-(x*x+y*y)/(2*sigma*sigma)));
}
void MainWindow::cpy_img_from_tmp(float*** tmp, int core_h, int core_w, int t_height, int t_width)
{
//qRed(old_image.pixel(j,i)
for (int i=0;i<core_h/2;i++)
for (int j=0;j<core_w/2;j++)
{//Углы
//R
tmp[i][j][0]=qRed(old_image.pixel(j,i));
tmp[t_height-1-i][t_width-1-j][0]=qRed(old_image.pixel((old_image.width()-1)-j,(old_image.height()-1)-i));
tmp[t_height-1-i][j][0]=qRed(old_image.pixel(j,(old_image.height()-1)-i));
tmp[i][t_width-1-j][0]=qRed(old_image.pixel((old_image.width()-1)-j,i));
//G
tmp[i][j][1]=qGreen(old_image.pixel(j,i));
tmp[t_height-1-i][t_width-1-j][1]=qGreen(old_image.pixel((old_image.width()-1)-j,(old_image.height()-1)-i));
tmp[t_height-1-i][j][1]=qGreen(old_image.pixel(j,(old_image.height()-1)-i));
tmp[i][t_width-1-j][1]=qGreen(old_image.pixel((old_image.width()-1)-j,i));
//B
tmp[i][j][2]=qBlue(old_image.pixel(j,i));
tmp[t_height-1-i][t_width-1-j][2]=qBlue(old_image.pixel((old_image.width()-1)-j,(old_image.height()-1)-i));
tmp[t_height-1-i][j][2]=qBlue(old_image.pixel(j,(old_image.height()-1)-i));
tmp[i][t_width-1-j][2]=qBlue(old_image.pixel((old_image.width()-1)-j,i));
}
for (int i=0; i<core_h/2;i++)
for (int j=0;j<t_width-(core_w-1);j++)
{//Vertical
//R
tmp[i][core_w/2+j][0]=qRed(old_image.pixel(j,i));
tmp[t_height-1-i][core_w/2+j][0]=qRed(old_image.pixel(j,(old_image.height()-1)-i));
//G
tmp[i][core_w/2+j][1]=qGreen(old_image.pixel(j,i));
tmp[t_height-1-i][core_w/2+j][1]=qGreen(old_image.pixel(j,(old_image.height()-1)-i));
//B
tmp[i][core_w/2+j][2]=qBlue(old_image.pixel(j,i));
tmp[t_height-1-i][core_w/2+j][2]=qBlue(old_image.pixel(j,(old_image.height()-1)-i));
}
for (int i=0; i<t_height-(core_h-1);i++)
for (int j=0;j<core_w/2;j++)
{//Horizontal
//R
tmp[core_h/2+i][j][0]=qRed(old_image.pixel(j,i));
tmp[core_h/2+i][t_width-1-j][0]=qRed(old_image.pixel((old_image.width()-1)-j,i));
//G
tmp[core_h/2+i][j][1]=qGreen(old_image.pixel(j,i));
tmp[core_h/2+i][t_width-1-j][1]=qGreen(old_image.pixel((old_image.width()-1)-j,i));
//B
tmp[core_h/2+i][j][2]=qBlue(old_image.pixel(j,i));
tmp[core_h/2+i][t_width-1-j][2]=qBlue(old_image.pixel((old_image.width()-1)-j,i));
}
for (int i=0; i<old_image.height();i++)
for (int j=0;j<old_image.width();j++)
{//Window
tmp[core_h/2+i][core_w/2+j][0]=qRed(old_image.pixel(j,i));
tmp[core_h/2+i][core_w/2+j][1]=qGreen(old_image.pixel(j,i));
tmp[core_h/2+i][core_w/2+j][2]=qBlue(old_image.pixel(j,i));
}
}
void MainWindow::gauss_filter(float ***tmp, float ***for_saving,float** core_g, int core_h, int core_w, int t_height, int t_width)
{
for (int i=(core_h/2);i<t_height-core_h/2;i++)
for (int j=(core_w/2);j<t_width-core_w/2;j++)
{
for (int m=0;m<(core_h/2)+1;m++)
for (int k=0;k<(core_w/2)+1;k++)
{//Red
for_saving[i][j][0]= for_saving[i][j][0]+tmp[i+m][j+k][0]*core_g[(core_h/2)+m][(core_w/2)+k];
if (k!=0)
{for_saving[i][j][0]= for_saving[i][j][0]+tmp[i+m][j-k][0]*core_g[(core_h/2)+m][(core_w/2)-k];}
if (m!=0)
{
for_saving[i][j][0]= for_saving[i][j][0]+tmp[i-m][j+k][0]*core_g[(core_h/2)-m][(core_w/2)+k];
if (k!=0)
{for_saving[i][j][0]= for_saving[i][j][0]+tmp[i-m][j-k][0]*core_g[(core_h/2)-m][(core_w/2)-k];}
}
//Green
for_saving[i][j][1]= for_saving[i][j][1]+tmp[i+m][j+k][1]*core_g[(core_h/2)+m][(core_w/2)+k];
if (k!=0)
{for_saving[i][j][1]= for_saving[i][j][1]+tmp[i+m][j-k][1]*core_g[(core_h/2)+m][(core_w/2)-k];}
if (m!=0)
{
for_saving[i][j][1]= for_saving[i][j][1]+tmp[i-m][j+k][1]*core_g[(core_h/2)-m][(core_w/2)+k];
if (k!=0)
{for_saving[i][j][1]= for_saving[i][j][1]+tmp[i-m][j-k][1]*core_g[(core_h/2)-m][(core_w/2)-k];}
}
//Blue
for_saving[i][j][2]= for_saving[i][j][2]+tmp[i+m][j+k][2]*core_g[(core_h/2)+m][(core_w/2)+k];
if (k!=0)
{for_saving[i][j][2]= for_saving[i][j][2]+tmp[i+m][j-k][2]*core_g[(core_h/2)+m][(core_w/2)-k];}
if (m!=0)
{
for_saving[i][j][2]= for_saving[i][j][2]+tmp[i-m][j+k][2]*core_g[(core_h/2)-m][(core_w/2)+k];
if (k!=0)
{for_saving[i][j][2]= for_saving[i][j][2]+tmp[i-m][j-k][2]*core_g[(core_h/2)-m][(core_w/2)-k];}
}
}
}
}
void MainWindow::normalize(float***mas, int height, int width)
{
float min,max;
min=mas[0][0][0];
max=mas[0][0][0];
for (int i=0;i<height;i++)
for (int j=0;j<width;j++)
{ if (mas[i][j][0]<min) min=mas[i][j][0];
if (mas[i][j][0]>max) max=mas[i][j][0];}
for (int i=0;i<height;i++)
for (int j=0;j<width;j++)
{ mas[i][j][0]=((mas[i][j][0]-min)/(max-min))*255;}
min=mas[0][0][1];
max=mas[0][0][1];
for (int i=0;i<height;i++)
for (int j=0;j<width;j++)
{ if (mas[i][j][1]<min) min=mas[i][j][1];
if (mas[i][j][1]>max) max=mas[i][j][1];}
for (int i=0;i<height;i++)
for (int j=0;j<width;j++)
{ mas[i][j][1]=((mas[i][j][1]-min)/(max-min))*255;}
min=mas[0][0][2];
max=mas[0][0][2];
for (int i=0;i<height;i++)
for (int j=0;j<width;j++)
{ if (mas[i][j][2]<min) min=mas[i][j][2];
if (mas[i][j][2]>max) max=mas[i][j][2];}
for (int i=0;i<height;i++)
for (int j=0;j<width;j++)
{ mas[i][j][2]=((mas[i][j][2]-min)/(max-min))*255;}
}