Multithreading for Image Processing

asked 2014-04-08 01:48:37 -0500

updated 2014-04-08 01:49:55 -0500

I do not have much experience with multithreading. I just want to create 4 threads. Devide image in 4 parts and process each part in different thread and join each part back. I have written following code.

#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/core.hpp>
#include <stdio.h>
#include <cstdlib>
#include <pthread.h>
#include <unistd.h>

using namespace std;

struct thread_data {
    int thread_id;
    cv::Mat img;
    cv::Mat retVal;
    double alpha;
};

void *processFrame(void *threadarg)
{
    //printf("processFrame started\n");
    struct thread_data *my_data;

    my_data = (struct thread_data *)threadarg;
    printf("accumulateWeighted starting %d\n", my_data->thread_id);
    printf("%d %d %d %d %d\n",my_data->thread_id, my_data->img.rows, my_data->img.cols, my_data->retVal.rows, my_data->retVal.cols);
    //cv::accumulateWeighted(my_data->img, my_data->retVal, my_data->alpha);
    printf("accumulateWeighted done %d\n", my_data->thread_id);
    pthread_exit(NULL);
}

int main(int argc, char* argv[])
{
    int NUM_THREADS = 4;
    pthread_t threads[NUM_THREADS];
    struct thread_data td[NUM_THREADS];
    int rc;

    cv::Mat img, acc;
    double alpha = 0.1;
    std::vector<cv::Mat> cutImg, accImg;

    img = cv::imread(argv[1]);
    acc = cv::Mat::zeros(img.size(), CV_32FC3);

    cutImg.push_back(cv::Mat(img, cv::Range(0, img.rows/2), cv::Range(0, img.cols/2)));
    cutImg.push_back(cv::Mat(img, cv::Range(0, img.rows/2), cv::Range(img.cols/2, img.cols)));
    cutImg.push_back(cv::Mat(img, cv::Range(img.rows/2, img.rows), cv::Range(0, img.cols/2)));
    cutImg.push_back(cv::Mat(img, cv::Range(img.rows/2, img.rows), cv::Range(img.cols/2, img.cols)));

    accImg.push_back(cv::Mat(acc, cv::Range(0, img.rows/2), cv::Range(0, img.cols/2)));
    accImg.push_back(cv::Mat(acc, cv::Range(0, img.rows/2), cv::Range(img.cols/2, img.cols)));
    accImg.push_back(cv::Mat(acc, cv::Range(img.rows/2, img.rows), cv::Range(0, img.cols/2)));
    accImg.push_back(cv::Mat(acc, cv::Range(img.rows/2, img.rows), cv::Range(img.cols/2, img.cols)));

    for(int i=0; i<NUM_THREADS; i++)
    {
        td[i].thread_id = i;
        td[i].img = cutImg[i];
        td[i].retVal = accImg[i];
        td[i].alpha = alpha;

        rc = pthread_create(&threads[i], NULL, processFrame, (void*)&td[i]);

        if(rc) {
            printf("Error: Unable to create thread\n");
            exit(-1);
        }
    }
    pthread_exit(NULL);
    return(1);
}

So when I run the program, most of the times it shows that the images that I passed have 0 rows.

accumulateWeighted starting 1
1 270 480 270 480
accumulateWeighted starting 3
3 0 480 0 480
accumulateWeighted done 3
accumulateWeighted starting 2
2 0 480 0 480
accumulateWeighted done 2
accumulateWeighted starting 0
0 270 480 270 480
accumulateWeighted done 0
accumulateWeighted done 1

What am I doing wrong here? I have tried looking for examples but couldn't find any. Is there any other way that this can be done?

edit retag flag offensive close merge delete

Comments

why would main call pthread_exit ? Also does the code pass a reference to part of the image or actually copy the image data to the vector?

GrumbleLion gravatar imageGrumbleLion ( 2014-04-28 16:03:46 -0500 )edit