Russian Qt Forum
Июнь 14, 2024, 10:23 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2 3 4   Вниз
  Печать  
Автор Тема: Многопоточное осветление пикселей  (Прочитано 25058 раз)
AlphaGh0St
Гость
« : Ноябрь 21, 2011, 13:56 »

Всем привет!
Мне нужно написать программку, которая в многопоточном режиме осветляет пиксели на картинке.
У меня есть документация по работе с потоками в Qt, но, что касается самого осветления пикселей...даже не представляю, с чего начать.

Подскажите, кто знает, как это делается.
Благодарю.
Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #1 : Ноябрь 21, 2011, 14:08 »

что касается самого осветления пикселей...даже не представляю, с чего начать.
Что вы подразумеваете под осветлением? Увеличение I в HSI?
Записан
AlphaGh0St
Гость
« Ответ #2 : Ноябрь 21, 2011, 15:10 »

У меня нет опыта а в обработке изображений. Просто нужно написать небольшую демонстрационную программку.
Программа, демонстрирующая преимущества многопоточности в Qt. В качестве работы для потоков, решил сделать осветление пикселей.

>> Увеличение I в HSI?
Не совсем понимаю вопрос.

Ну суть какова: мы выбрали картинку, загрузили её в программу (QPixmap или QImage, что лучше?)).
Далее в многопоточном режиме осветляем картинку пиксель за пикселем.
Осветление - оно и есть осветление, сделать картинку чуть ярче, что-ли.
Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #3 : Ноябрь 21, 2011, 15:39 »

>> Увеличение I в HSI?
Не совсем понимаю вопрос.
http://ru.wikipedia.org/wiki/HSI
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Ноябрь 21, 2011, 17:31 »

Так вполне устроит HSV модель. Берете пиксель (RGB). перегоняете его в HSV (QColor::getHsv), увеличиваете V и записываете назад в RGB (QColor::setHsv). Каждой нитке даете определенное число строк для обработке (проще всего)
Записан
AlphaGh0St
Гость
« Ответ #5 : Ноябрь 23, 2011, 18:51 »

Спасибо, помогло!
Продолжу работать над программой...
Записан
AlphaGh0St
Гость
« Ответ #6 : Ноябрь 24, 2011, 12:25 »

Такой вопрос:
Определил класс для многопоточного осветления пикселей
Код:
class ImageThread : public QThread { ... };

В главном классе создаю несколько потоков:
Код:
    for(int i = 0; i < threadsLimit; i++)
        imgThread[i].run();

При выводе отладочной информации, qDebug показывает, что у всех потоков один и тот же идентификатор.
Например:
При threadsLimit = 1, qDebug показывает:
Код:
ID: 0xc10 

При threadsLimit = 2, qDebug показывает:
Код:
ID: 0xc10 
ID: 0xc10

При threadsLimit = 3, qDebug показывает:
Код:
ID: 0xc10 
ID: 0xc10
ID: 0xc10

Может я где-то ошибся и, действительно, создаётся только один поток?
Записан
BRE
Гость
« Ответ #7 : Ноябрь 24, 2011, 12:31 »

Потоки запускаются методом start!!!
Записан
Bepec
Гость
« Ответ #8 : Ноябрь 24, 2011, 13:23 »

run - выполнение функции run;
start - запуск потока, который выполняет функцию run;
Записан
AlphaGh0St
Гость
« Ответ #9 : Ноябрь 24, 2011, 15:14 »

Ок, с этим ясно.
Возникла другая проблема.

При запуске программы в одном потоке, проблем нет. Но если запускать её хотя бы в двух потоках, то программа вылетает.
Просто завершается с кодом "-1073741819" или ему подобным.

Тут запускаем потоки из главного класса:
Код:
    for(int i = 0; i < threadsLimit; i++)
        imgThread[i].start();

А вот метод run(). Указатель на картинку (QImage) получаем из главного класса, по этому блокируем её мьютексом.
Код:
void ImageThread::run(){
    QSize countOfPixels = t_image->size(); // кол-во пикселей
    QRgb rgb;
    QColor color;
    int h = 0, s = 0, v = 0;

    time.start(); // замеряем время выполнения

    // проходим по всем пикселям
    for(int i = 0; i < countOfPixels.width(); i++){
        for(int j = 0; j < countOfPixels.height(); j++){

            // берём текущий пиксель
            t_mutexRead.lock();
                rgb = t_image->pixel(i, j);
            t_mutexRead.unlock();

            // увеличиваем яркость
            color.setRgb(rgb);
            color.getHsv(&h, &s, &v);
            v += t_brightnessValue; // значение, на которое надо увеличить яркость
            color.setHsv(h, s, v);

            // сохраняем изменённый пиксель
            t_mutexWrite.lock();
                t_image->setPixel(i, j, color.rgb());
            t_mutexWrite.unlock();
            }
        }

    // сообщаем главному классу, что работа завершена и время выполнения.
    emit workDone("MS:" + QString("%1").arg(time.elapsed()));
}

Из отладочной информации тоже не стало ясно, почему программа вылетает. Завершение происходит ни на одном и том же месте, а в разных местах: то на записи обработанного пикселя, то на увеличении яркости.

Ещё одна странность. Из отладки видно, что при запуске программы в двух потоках, получает управление только один поток. Этот поток входит в цикл и начинает работать, но другого потока нет. Этот один поток продолжает работать, а потом программа вылетает.

Вот отладочная информация:
Код:
Видим, что поток с ID 0xcd8 вошёл в метод, вошёл в первый цикл и во второй.
THREAD BEGIN  | ID:  0xcd8
ENTER IN 1ST LOOP  | ID:  0xcd8
ENTER IN 2ND LOOP  | ID:  0xcd8


Далее начинается выполнение:
BLOCK MUTEX AND READ  | ID:  0xcd8
CHANGE DATA  | ID:  0xcd8
BLOCK MUTEX AND WRITE  | ID:  0xcd8
И так много-много раз...
...

И в конце:
BLOCK MUTEX AND READ  | ID:  0xcd8
CHANGE DATA  | ID:  0xcd8
И программа вылетела

Не могу понять, в чём проблема.
Подскажите, где я ошибся?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #10 : Ноябрь 24, 2011, 16:06 »

Писал прямо здесь, ошибки возможны
Код
C++ (Qt)
// члены класса ImageThread
// mSelfIndex - индекс нитки
// mTeamCount - число ниток-обработчиков
void ImageThread::run()
{
   QColor color;
   int h, s, v;
 
   time.start(); // замеряем время выполнения
 
   int numRow = t_image.height() / mTeamCount;  // число строк для обработки
   int begRow = numRow * mSelfIndex;                // первая стока
   int endRow = (mSelfIndex == mTeamCount - 1) ? t_image.height() : (begRow + numRow); // предел
 
   for(int row = begRow; row < endRow; ++row) {
       unsigned int * data = (unsigned int *) t_image.scanLine(row);
       for(int col = 0; col < t_image.width(); ++col){
           unsigned int & pix = data[col];
           color.setRgb(qRed(pix), qGreen(pix), qBlue(pix));
           color.getHsv(&h, &s, &v);
           v += t_brightnessValue; // значение, на которое надо увеличить яркость
           v = qMin(v, 255);
           color.setHsv(h, s, v);
 
           // сохраняем изменённый пиксель
           pix = qRgba(color.red(), color.green(), color.blue(), qAlpha(pix));
        }
    }
 
   // сообщаем главному классу, что работа завершена и время выполнения.
   emit workDone("MS:" + QString("%1").arg(time.elapsed()));
}
« Последнее редактирование: Ноябрь 24, 2011, 18:11 от Igors » Записан
AlphaGh0St
Гость
« Ответ #11 : Ноябрь 24, 2011, 19:29 »

В циклах всё понятно, код замечательный у Вас ))

Не понятно только вот здесь:
Код:
// mSelfIndex - индекс нитки
// mTeamCount - число ниток-обработчиков

int numRow = t_image.height() / mTeamCount;  // число строк для обработки
int begRow = numRow * mSelfIndex;                // первая стока
int endRow = (mSelfIndex == mTeamCount - 1) ? t_image.height() : (begRow + numRow); // предел

mTeamCount - кол-во созданных потоков, полагаю?
А вот mSelfIndex? Индекс... в смысле идентификатор потока? Или его порядковый номер?

Вот тут что-то не совсем понял...
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #12 : Ноябрь 24, 2011, 19:57 »

А вот mSelfIndex? Индекс... в смысле идентификатор потока? Или его порядковый номер?

Вот тут что-то не совсем понял...
Порядковый - нитке нужно знать какие строки имеджа она будет обрабатывать. Просто передавайте в конструктор и еще: лучше сделать контейнер указателей (а не самих ImageThread), напр

Код
C++ (Qt)
ImageThread::ImageThread( int iIndex, int iCount ) :
 mSelfIndex(iIndex),
 mTeamCount(iCount)
{
...
}
 
// создаем все нитки
QVector <ImageThread *> theThread;
for (int i = 0; i < numThreads; ++i)
theThread.push_back(new ImageThread(i, numThreads));
 
// удаляем (после того как они отработали)
for (int i = 0; i < numThreads; ++i)   // ну или пресловутое qDeleteAll
delete theThread[i];
 
theThread.clear();
 
Записан
Sahab
Гость
« Ответ #13 : Ноябрь 24, 2011, 21:42 »

OpenMP
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #14 : Ноябрь 24, 2011, 22:14 »

В данной задаче OpenMP ни к селу ни к городу. Ну разве что есть желание "пособирать"  Улыбающийся
Записан
Страниц: [1] 2 3 4   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.144 секунд. Запросов: 19.