Dividing image to tiles in qt - c++

I have a very big image (31000X26000 pixels). I need to create tiles of a given size from this image and store them. I'm trying to use Qt's QImagereader but I've notice that after setClipRect for the second time, it can't read from the image.
The code I have so far works, but is very slow (this first row takes 7 seconds, the second 14, the third 21 and so on...)
for (int i = 0; i < tilesPerRow; i++){
for (int j = 0; j < tilesPerCol; j++){
QImageReader reader(curImage);
reader.setClipRect(QRect(j*(tileSize-OVERLAP),i*(tileSize-OVERLAP),tileSize,tileSize));
QImage img = reader.read();
if (img.isNull())
qDebug() << reader.errorString();
else{
retImg.setTile(img,i,j);
}
}
}
What am I doing wrong? Is it reasonable that I have to create a new reader each time? Does the location of the tile I'm trying to access affects speed and performance? If you have any suggestions on a better practice, I would appreciate it

Related

what is the fastest way to run a method on all pixels in opencv (c++)

I have several tasks to do on each pixel in opencv. I am using a construct like this:
for(int row = 0; row < inputImage.rows; ++row)
{
uchar* p = inputImage.ptr(row);
for(int col = 0; col < inputImage.cols*3; col+=3)
{
int blue=*(p+col); //points to each pixel B,G,R value in turn assuming a CV_8UC3 colour image
int green=*(p+col+1);
int red=*(p+col+2);
// process pixel }
}
This is working, but I am wondering if there is any faster way to do this? This solution doesn't use any SIMD or any paralle processing of OpenCV.
What is the best way to run a method over all pixels of an image in opencv?
If the Mat is continuous, i.e. the matrix elements are stored continuously without gaps at the end of each row, which can be referred using Mat::isContinuous(), you can treat them as a long row. Thus you can do something like this:
const uchar *ptr = inputImage.ptr<uchar>(0);
for (size_t i=0; i<inputImage.rows*inputImage.cols; ++i){
int blue = ptr[3*i];
int green = ptr[3*i+1];
int red = ptr[3*i+2];
// process pixel
}
As said in the documentation, this approach, while being very simple, can boost the performance of a simple element-operation by 10-20 percents, especially if the image is rather small and the operation is quite simple.
PS: For faster need, you will need to take full use of GPU to process each pixel in parallel.

OpenCV execution speed (for loops and meanStdDev)

I'm fairly new to OpenCV and C++ ( learning it now after doing a fair share if image processing on MATLAB and LabView).
I'm having a weird issue I wanted to ask your opinion.
I'm trying to do a fairly simple thing: moving window 1x9 stdev on a gray scaled image (~ 4500X2000 pix).
here is the heart of the code:
Mat src = imread("E:\\moon project\\Photos\\Skyline testing\\IMGP6043 sourse.jpg");
Scalar roi_mean, roi_stdev;
Mat stdev_map(src.rows, src.cols, CV_64FC1,Scalar(0));
cvtColor(src, src_gray, CV_BGR2GRAY);
int t = clock();
for (int i = 0; i < src_gray.cols - 1; i++)
{
for (int j = 0; j < src_gray.rows - 8; j++)
{
meanStdDev(src_gray.col(i).rowRange(j,j+9), roi_mean, roi_stdev);
stdev_map.at<double>(j, i) = roi_stdev[0];
}
}
t = clock() - t;
cout << "stdev calc : " << t << " msec" << endl;
Now on the aforementioned image it takes 35 seconds to run the double loop (delta t value) and even if I throw away the meanStdDev and just assign a constant to stdev_map.at(j, i) it still takes 14 seconds to run the double loop.
I'm pretty sure I'm doing something wrong since on Labview it takes only 2.5 seconds to chew this baby with the exact same math.
Please help me.
To answer your question and some of the comments: do compile the lib in release mode will surely increase the computation time, by what order it depends, for example if you are using eigen it probably will speed things up a lot.
If you really want to do the loop by yourself, consider getting the row pointer to the data directly mat.data, or mat.ptr<cv::Vec3b>.
If you want to speed up the task of computing mean/stdDev on any part of your image, then use integral images. The doc is pretty clear about it, and I'm pretty sure it will take less than 2.5s probably even in debug mode.

What is the fastest way to access a pixel in QImage?

I would like to know what is the fastest way to modify a portion of a QImage.
I have this piece of code that has to be executed with a frequency of 30Hz. It displays an image through a sort of keyhole. It is not possible to see the entire image but only a portion inside a circle. The first for-loop erases the previous "keyhole portion displayed" and the second updates the position of the "displayed keyhole".
for (int i = (prev_y - r_y); i < (prev_y + r_y); i++){
QRgb *line = (QRgb *)backgrd->scanLine(i);
for(int j = (prev_x - r_x); j < (prev_x + r_x) ; j++){
if((i >= 0 && i < this->backgrd->height()) && (j >= 0 && j < this->backgrd->width()))
line[j] = qRgb(0,0,0);
}
}
prev_x = new_x; prev_y = new_y;
for (int i = (new_y - r_y); i < (new_y + r_y); i++){
QRgb *line = (QRgb *)backgrd->scanLine(i);
QRgb *line2 = (QRgb *)this->picture->scanLine(i);
for(int j = (new_x - r_x); j < (new_x + r_x) ; j++){
if ((((new_x - j)*(new_x - j)/(r_x*r_x) + (new_y - i)*(new_y - i)/(r_y*r_y)) <= 1) && (i >= 0) && (i < this->picture->height())&& (j >= 0) && (j < this->picture->width()))
line[j] = line2[j];
}
}
this->current_img = this->backgrd;
}
this->update(); //Display QImage* this->current_img
If I analyse the timestamps of the program I find a delay in the flow of execution every time it is executed...
Is it so high consuming to access a pixel in a QImage? Am I doing something wrong?
Is there a better alternative to QImage for a Qt program?
How about prerendering your 'keyhole' in an array/qimage and doing a bitwise AND with the source?
Original pixel && black => black
Original pixel && white => original pixel
You have a lot of conditions in the innermost loop (some can be moved out though), but the circle radius calculation with the multiplies and divides looks costly. You can reuse the keyhole mask for every frame, so no calculations need be performed.
You could move some of the conditions at least to the outer loop, and maybe pre-compute some of the terms inside the conditions, though this may be optimized anyway.
Call update only for the rectangle(s) you modified
Where do you get the time stamp? Maybe you lose time somewhere else?
Actually I understood it wasn't pixel acces that was slow, but the rendering.
During the tests I did I used plain color images, but these kind of images are much faster to render than complex images loaded from file. With other tests I realized was the rendering that was slow.
The fastest way to render an QImage is first of all to transform it using
public: static QImage QGLWidget::convertToGLFormat(const QImage &img)
then the image can be fastly manipulated (it preserves bits() scanline() width() and height() functions)
and can be displayed very fast by openGL (no further conversions are necessary)
QPainter painter(this);
glDrawPixels(img.width(), img.height(), GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
painter.end();
As far as I know the fastest way to access the data of a QImage is to use QImage::bits() which give you direct access to the data of QImage.
For your problem, A better approch will be to do as Bgie suggested : using a array representing the keyhole and doing only a bitwise AND operation.
it will help to choose the correct format for your Image, the format RGB32 and ARG32_Premultiplied_ARGB32 are the fastest. Don't use ARGB32 if you don't need it.

Submatrix in C++

I have a programming issue regarding the extraction of a subimage (submatrix) from a bigger image (matrix). I have two points (upper and lower bound of the subimage i want to extract) and i want to extract the subimage from the bigger one based on these points. But I can't find how to do thins with C/C++.
I know it's very easy to do with matlab. Suppose these two points are (x_max,y_max) and (x_min,y_min). To extract the subimage I just need to code the following:
(MATLAB CODE)-> small_image=big_image(x_min:x_max,y_min,y_max);
But in C i can't use an interval of indexes with : as i do with Matlab. Does anybody here faced this problem before?
If you are doing image processing in C/C++, you should probably use OpenCV.
The cv::Mat class can do this using a Region Of Interest (ROI).
In straight c++, you'd use a loop.
int* small_im[]; // or whatever the syntax is
int i = 0, j = 0;
for (i = 0; i < (x_max-x_min); i++)
{
for (j = 0; j < (y_max-y_min); j++)
{
small_im[i][j] = big_im[x_min+i][y_min+j];
}
}

getting the values of cv::Mat

I've program, in which I calcul the mean value of multiples frames, when I save this mean value wich is a frame I got a 965KB file, but I do the same thing with SCILAB which based on OpenCV I get a 5.93MB which sound more logical. anyway I decid to write my frame using fwrite and here what did:
cv::Mat meanFrame= cv::Mat::zeros(height,width,CV_32FC3);
cv::Mat frameR;
FILE* inpR = NULL;
...... //after calculating the meanFrame
inpR = fopen("d:\\red.txt","wb+");
for(int row = 0; row < meanFrame.rows; ++row) {
for (int col = 0; col < meanFrame.cols; ++col) {
std::cout << meanFrame.at<cv::Vec3f>(row, col)[1] <<std::endl;
std::cout << meanFrame.at<cv::Vec3f>(row, col)[2] <<std::endl;
fwrite(&resultframe.at<cv::Vec3f>(row,col )[0],sizeof(float),1,inpR);
}
}
fcloseall();
I can see the pf channel 1 and 2 but when I opencv the file red.txt I get :
€€<€€<€€<€€<€€<€€<€€<€€<€€<€€<€€<€€<€€.......
any idea what I'm missing here, after that I want to load those file in SCILAB and than save the frame as file.
thanks for your help!
You are writing the binary data - how a float is stored in memory.
When you view the file (in the editor or on the commandline) it thinks this is text data and is trying to interpret it as characters.
If you need to read this values into another program then you can use fwrite and fread (although you might have an issue with byte ordering if you have different CPUs)
If you just want to see the results, or want slightly more work to read them into another program, you can just print the values with
printf("%f", resultframe.at<cv::Vec3f>(row,col )[0]);