Using BOOST::UBLAS and FFTW together for image processing - c++

Is there a possibility to use a boost matrix along FFTW? if so how do you do it?
what i basically have is
QPixmap pixmap("lena.bmp");
// resize input image
pixmap = pixmap.copy(512,512,128,128);
pixmap = pixmap.scaled(128,128);
QImage image = pixmap.toImage();
QRgb col;
int g;
int width = pixmap.width();
int height = pixmap.height();
matrix<double> m(width,height);
for (int j = 0; j < m.size2(); j++)
{
for (int i = 0; i < m.size1(); i++)
{
m(i,j) = 0;
m(i,j) = qGray(image.pixel(i,j));
}
}
I want to perform FFTW on the matrix 'm' and then redisplay the fft of the image. how do i do this?

you can do is first read your image into an array, then apply the FFTW as per your needs on this array and then fill this array into a boost ublas matrix and then use it.
int a[width][height];
for (int j = 0; j < width; j++)
{
for (int i = 0; i < height; i++)
{
a[i][j] = qGray(image.pixel(i,j));
}
}
//apply fftw
matrix<double> m(width,height);
for (int j = 0; j < width; j++)
{
for (int i = 0; i < height; i++)
{
m(i,j) = fft_a[i][j];
}
}
I hope this works

Related

Bitshifts in OpenCV C++

I am trying to rightshift all the pixels of a Image by 1 bit. I don't see any vectorized way to do this. As of now, the only solution that I have is as follows
void round_down(cv::Mat& image) {
int channels = image.channels();
int num_rows = image.rows;
int num_cols = (image.cols * channels);
if (image.isContinuous()) {
num_cols *= num_rows;
num_rows = 1;
}
for (int i = 0; i < num_rows; ++i) {
uchar* row_ptr = image.ptr<uchar>(i);
for (int j = 0; j < num_cols; ++j) {
row_ptr[j] >>= 1;
}
}
}
Are there any OpenCV C++ functions for bitwise leftshift and right shifts?
If not what is the best time optimized way to do it ?

I cant iterate through pixels of all the image, it is iterating through parts of it. OpenCV

I have the following code:
void white(Mat&src,Mat&dst){
double h = src.cols;
double w = src.rows;
dst = src.clone();
for (int i = 0; i < dst.rows; i++) {
for (int j = 0; j < dst.cols; j++) {
dst.at<uchar>(i, j) = 255;
}
}
}
My expected result is to get a completely white image, however, I get this result:
Input Image:
Output Image:
It's a color image. Each pixel consists of 3 values. You have to set each color channel
void white(Mat&src,Mat&dst){
double h = src.cols;
double w = src.rows;
dst = src.clone();
for (int i = 0; i < dst.rows; i++) {
for (int j = 0; j < dst.cols; j++) {
for (std::size_t c = 0; c < 3; ++c) {
dst.at<Vec3b>(i, j)[c] = 255;
}
}
}
}

C++: Reshape vector to 3D array

Edit: I have uploaded the vector to Drive as a text file, in case anyone want to have a look: https://drive.google.com/file/d/0B0wsPU8YebRQbDUwNFYza3ljSnc/view?usp=sharing
I'm trying to reshape my vector h into a 3D array. h contains 295788 elements. In this case height = 314, width = 314 and depth = 3.
Basically what I'm trying to do is what MATLAB does with its reshape function.
h = reshape(h, height, width, depth)
This is my attempt so far, but when I print it all I see is zeroes, which is not right. I have double checked that h contains the numbers I'm expecting.
vector<vector<vector<double> > > array3D;
int height = 314, width = 314, depth = 3;
// Set up sizes
array3D.resize(height);
for (int i = 0; i < height; ++i) {
array3D[i].resize(width);
for (int j = 0; j < width; ++j)
array3D[i][j].resize(depth);
}
for (int i = 0; i < height; i++)
{
array3D[i][0][0] = h[i];
for (int j = 0; j < width; j++)
{
array3D[i][j][0] = h[i+j];
for (int k = 0; k < depth; k++)
{
array3D[i][j][k] = h[i+j+k];
}
}
}
Printing:
for (vector<vector<vector<double>>>::const_iterator i = array3D.begin(); i != array3D.end(); ++i)
{
for (vector<vector<double>>::const_iterator j = i->begin(); j != i->end(); ++j)
{
for (vector<double>::const_iterator k = j->begin(); k != j->end(); ++k)
{
cout << *k << ' ';
}
}
}
So my question is, how do I convert my vector into a 3D array properly?
I managed to do this by using Eigen::Tensor as suggested by Henri Menke. I ended up creating an array for the initial 314x314x3 matrix, and then another one for the 300x300x3 matrix. It's neither fast nor pretty, but for now that is what I could come up with. Looks like this.
For clarification: margin is calculated further up in the code, but in this example with the 314x314x3 matrix it's margin=7. h is a vector with 295788 elements. nrh=314, nch=314 and nradii=3.
Tensor<int, 3> t(nrh, nch, nradii);
int counter = 0;
for (int k = 0; k < nradii; k++)
{
for (int col = 0; col < nch; col++)
{
for (int row = 0; row < nrh; row++)
{
t(row, col, k) = h[counter];
counter += 1;
}
}
}
int height = nrh - margin * 2;
int width = nch - margin * 2;
int depth = nradii;
Tensor<int, 3> out(height, width, depth);
int count1 = 0, count2 = 0, count3 = 0;
for (int k = 0; k < depth; k++)
{
for (int j = margin; j < nch - margin; j++)
{
for (int i = margin; i < nrh - margin; i++)
{
out(count1, count2, count3) = t(i, j, k);
count1 += 1;
}
count1 = 0;
count2 += 1;
}
count2 = 0;
count3 += 1;
}
Edit: Solution #2 with Tensor.slice()
int height = nrh - margin * 2;
int width = nch - margin * 2;
int depth = nradii;
Tensor<int, 3> tensor(height, width, depth);
DSizes<ptrdiff_t, 3> indices(margin, margin, 0);
DSizes<ptrdiff_t, 3> sizes(height, width, nradii);
tensor = t.slice(indices, sizes);
How about:
array3D[i][j][k] = h[i*(depth*width)+j*depth+k];
That may or may not be scanning the vector in the correct order.
Notice how when the index k resets the index j increments so you move on exactly one until the index j resets in which case i increments and the same. It's easy to show this calculation reads every element exactly once.
I'd normally expect a width, height then depth and you're scanning in the opposite order!
Footnote: Depending on the application is may be worthwhile to just access the vector using this approach. In general it turns out to be faster than accessing a vector of vectors of vectors. That can be relevant when dealing with massive arrays.
Actually, your the structure of your code is already ok, however, there are two mistakes:
The lines
array3D[i][0][0] = h[i];
and
array3D[i][j][0] = h[i+j];
are pointless. You are overwriting those entries later on with the line
array3D[i][j][k] = h[i+j+k];
The index calculation for h[] is wrong: You must multiply the row index by the length of a row before adding the cell index. The assignment should look like this:
array3D[i][j][k] = h[(i*width+j)*depth+k];
Otherwise, you will get the same result for (i, j, k) == (3, 2, 1) as for (i, j, k) == (1, 3, 2), which is obviously wrong. In the index calculation above, I have assumed that k is the fastest changing dimension. If that is not the order in which your data is stored in h, you need to change the positions of i, j, and k and adjust the factors accordingly.
Putting this together, your assignment loop should read:
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
for (int k = 0; k < depth; k++) {
array3D[i][j][k] = h[(i*width+j)*depth+k];
}
}
}
Slightly off-topic:
If you were using C instead of C++, you could "simply" do this:
size_t dataSize;
//Create a real 3D array with the dimensions (height, width, depth).
double (*array3D)[width][depth] = malloc(dataSize = height*sizeof(*array3D));
//Copy over the data from the file.
memcpy(array3D, h, dataSize);
//Print the array contents:
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
for (int k = 0; k < depth; k++) {
printf("%d ", array3D[i][j][k]);
}
}
}
This uses a real 3D array instead of an array of pointers to arrays of pointers to arrays of doubles (which is roughly what a vector<vector<vector<double>>> is). However, this cannot be done in C++ as C++ does not allow for array types with dynamic sizes as C does.

window operation by Pointer of image

If we access pixel by a pointer using step and data of Mat Image. see example below
int step = srcimg.step;
for (int j = 0; j < srcimg.rows; j++) {
for (int i = 0; i < srcimg.cols; i++) {
//this is pointer to the pixel value.
uchar* ptr = srcimg.data + step* j + i;
}
}
Question:
How can we perform 3x3 weighted avg operations with image step by a pointer?
thanks
You mustn't use data field in opencv because memory is not allways continuous. you can check this using isContinuous() method.
Now you can do like this (image type is CV_8UC1)
for (int i = 1; i < srcimg.rows-1; i++)
{
for (int j = 1; j < srcimg.cols-1; j++)
{
int x=0;
for (int k=-1;k<=1;k++)
{
uchar* ptr=srcimg.ptr(k+i)+j-1;
for (int l=-1;l<=1;l++,ptr++)
x +=*ptr;
}
}
}
image border are not processed. Now if you want to blur an image use blur method
You can use this post too
I am doing something like this .
int sr = 3;
for (int j = 0; j < srcimg.rows; j++) {
for (int i = 0; i < srcimg.cols; i++) {
uchar* cp_imptr = im.data;
uchar* tptr = im.data + imstep *(sr + j) + (sr + i);
int val_tptr = cp_imptr [imstep *(sr + j) + (sr + i)]; //pointer of image data amd step at 3x3
int val_cp_imptr = cp_imptr[imstep *j + i];
double s = 0;
for (int n = templeteWindowSize; n--;)
{
for (int m = templeteWindowSize; m--;)
{
uchar* t = tptr; //pointer of template
// sum
s += *t;
t++;
}
t += cstep;
}
}
cout << endl;
}

How to accessing data in cv::mat when the image type is not known at deisgn time?

I have a set of input images and one output image and I need to combine the input images and create output image.
I have this code:
for (int j = 0; j < Height; ++j)
{
for (int i = 0; i < Width; ++i)
{
int xx,yy,Id;
algo.calXY(i, j, xx, yy,Id);
cv::Vec3b value=cubeImage.images[Id].at<cv::Vec3b>(yy,xx);
output.at<cv::Vec3b>(j,i)=value;
}
}
This code works only if the input images are RGB without alpha channel.
How can I change it to so if input images are ARGB, it works properly?
I tried to replace cv::Vec3b with cv::Vec<uchar, output.channels>, but it is not compiling as it needs a compile time variable for type.
You can make this work by copying one channel at a time:
for (int j = 0; j < Height; ++j)
{
uchar* orow = output.ptr<uchar>(j);
for (int i = 0; i < Width; ++i)
{
int xx, yy, Id;
algo.calXY(i, j, xx, yy, Id);
//cv::Vec3b value=cubeImage.images[Id].at<cv::Vec3b>(yy,xx);
uchar* mrow = cubeImage.images[Id].ptr<uchar>(yy);
mrow += xx * output.channels();
// output.at<cv::Vec3b>(j,i)=value;
for(int c = 0; c < output.channels(); ++ c)
*orow++ = *mrow++;
}
}