Фильтр Гаусса, обработка изображения с помощью процессов и потоков

Рейтинг: 0Ответов: 1Опубликовано: 19.12.2014

Доброго времени суток, уважаемые программисты!

Есть проблемка. Дано изображение, которое будет обрабатываться фильтром Гаусса, код обработки есть, все прекрасно работает, НО препод для проверки дает картинку 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;}

}

Ответы

▲ 1

Можно сделать несколько потоков, и каждому передавать какой-нибудь диапазон. Например, есть изображение 10х10, "делим" обработку между потоками

  1. Поток№1 обрабатывай часть изображения 2х10 и указать сдвиг с левого верхнего края (либо можно указать диапазон в пикселях с [0,0] до [1,9])
  2. Поток№2 тоже что и у первого только сдвиг другой (в пикселях с [2,0] до [3,9])
  3. ... еще потоки
  4. ?????
  5. Profit