C++ OpenCV Matrix conversion into coder::array unsigned short - c++

I read a DICOM image into an OpenCV matrix, I need to store the pixel data into coder::array<unsigned short, 2U> array because I have a C++ code generated function (using MATLAB) that takes this data type as an input.
I tried the below code expecting the pixel data of rows and columns to be stored in each of the array dimentions.
coder::array<unsigned short, 2U> argInit_ImageArray(const cv::Mat& image)
{
unsigned short rows = image.rows;
unsigned short cols = image.cols;
const unsigned short* pixelData = (unsigned short*)image.data;
coder::array<unsigned short, 2U> result({rows, cols});
unsigned short *pixelDataPointer = (unsigned short*)pixelData;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
result.at(i,j) = pixelDataPointer[i * cols + j];
}
}
return result;
}

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 ?

Writing array into bitmap c++

I have trouble with writing array into a bitmap again, so basically I read data from .bmp file where I get data of pixels and I want to make B and R = 0 so here it is my code:
int row_padded = ( Picture.biWidth*3 + 3) & (~3);
unsigned char* data = new unsigned char [row_padded];
unsigned char tmp;
for(int i = 0; i < Picture.biHeight; i++)
{
fread(data, sizeof(unsigned char), row_padded, plik);
for(int j = 0; j < Picture.biWidth*3; j += 3)
{
data[j] = 0;
data[j+2] = 0;
}
}
Now when I have my B and R = 0 I want to save it again to the same file, so I am using:
for(int j = 0; j< Picture.biHeight; j++)
{
fwrite(data,1,Picture.biWidth, f);
}
but nothing works.
fwrite(data,1,Picture.biWidth, f) must be fwrite(data,1,row_padded, f) no ? else only the first third of the bytes are written
note : by definition sizeof(unsigned char) is 1

FFTW wrong backward transform on 2D image [with Qt]

I created an application in Qt, which allow me to open image and use 2D FFT transform with FFTW library. The problem is that I can not retrieve proper pixel values with backward transformation. But let's start from begining.
This is how looks my FFTW function which I use
void FFTInterface::FFTW(int rows, int cols, QColor **imageInput,fftw_complex * in, fftw_complex * out)
{
fftw_plan g;
g = fftw_plan_dft_2d(rows, cols, in, out, FFTW_FORWARD, FFTW_MEASURE);
int k = 0;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
in[k][0] = imageInput[i][j].red();
in[k][1] = 0.0;
k++;
}
}
fftw_execute(g);
fftw_destroy_plan(g);
}
rows, cols are size of an image, imageInput is the array of QColor, which keep the pixels value (in greyscale), in and out are object of fftw_complex, input and output arrays.
This function give me some result, which has to be show. To do this, I made some kind of scalling. Firstly, I use abs() function on every value, to be sure that it has positive value. After that, I scale the result.
void FFTInterface::Abs(fftw_complex *out, int rows, int cols)
{
int k = 0;
for(int i = 0; i < rows; i++){
for(int j = 0; j<cols; j++){
out[k][0] = abs(out[k][0]);
out[k][1] = abs(out[k][1]);
k++;
}
}
}
void FFTInterface::Scale(fftw_complex * in,int rows, int cols)
{
float c = 255.0 / log(1+Max(in,rows,cols));
int k = 0;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
in[k][0] = c*log(1+in[k][0]);
in[k][1] = c*log(1+in[k][0]);
k++;
}
}
}
This process give me something that I need. Image looks ok. But I have problem to revert image to it's original.
Function for BACKWARD is like below
void FFTInterface::IFFTW(int rows, int cols, fftw_complex * in, fftw_complex * out)
{
fftw_plan g;
g = fftw_plan_dft_2d(rows, cols, in, out, FFTW_BACKWARD, FFTW_MEASURE);
int k = 0;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
in[k][1] = 0.0;
k++;
}
}
fftw_execute(g);
fftw_destroy_plan(g);
}
I found somewhere that it's not normalized (the results are VERY BIG). To normalize I just divide values by N (256,512 etc.) - width or height of the image (it's always a square), but the values are different then the original ones.
Do you have any idea where I'm missing something? Scalling? I should maybe use other fft method from library? I have stucked.
By taking the absolute value and scaling the complex components for the purpose of displaying the image you are modifying the data in such a way that the inverse transform no longer gives you the original input. To avoid this problem I would suggest you create a copy of the data you wish to display before you scale it. Also, make sure not to forget that the input to the inverse transform should be the output from the forward transform (or the last output in a signal processing chain as may be).
In pseudo-code you could do this like so:
interface.FFTW(rows, cols, imageInput, in, out);
size_t N = rows*cols;
fftw_complex* todisplay = fftw_malloc(N);
std::copy(out, out+N, todisplay);
interface.Abs(todisplay);
interface.Scale(todisplay);
... display "todisplay" on your Qt user interface
fftw_free(todislay);
interface.IFFTW(rows, cols, out, reconstructed);

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++;
}
}

Iterating over 2D vector of "char" in C++, blank characters are not printing out

I am currently working on a battleship text based game and I am switching my container that I am using to store the board from a 2D array of char to a 2D vector. In the code snipped below I am initializing the entire board and setting all the characters in it to be blank spaces to begin with. What follows this is all of my code to create the board etc.
const int width = 100;
const int height = 35;
vector< vector<char> > buffer(width, vector<char>(height,0));
for (int y = 0; y < height; ++y)
for (int x = 0; x < width; ++x)
buffer[x][y] = ' ';
When I am going to output the board to the screen I am trying to use the iterators that are provided for vectors. Only problem I am having is that when using the iterator it seems to ignore blank spaces in my vector so my game board does not look as it should. Just using a double for loop to iterate through the vector then the output is fine.
vector<vector<char> >::const_iterator row;
vector<char>::const_iterator col;
for (row = buffer.begin(); row != buffer.end(); row++) {
for (col = row->begin(); col != row->end(); col++) {
cout << *col;
}
cout << endl;
}
This is the first time im attempting to use vectors so im stumped. Anyone know why it would be ignoring the blank characters?
My first question is: "why are you using vectors for a simple 2-D array?" I would simply use a two-dimensional array and be done with it. An efficient way to allocate a 2-D array of objects with a single malloc() call (so it can be freed with a single free() call) is:
/* set up the memory for a 2D matrix with entries of size "size" */
void** matrix2D(long rows, long columns, long size)
{
long i;
unsigned long long row_size = (unsigned long long)columns * (unsigned long long)size;
unsigned long long data_size = ((unsigned long long)rows * (unsigned long long)columns + 1) * (unsigned long long)size;
unsigned long long pointer_size = (unsigned long long)rows * sizeof(void*);
void** result;
if ( (result = (void**)malloc((size_t)(data_size + pointer_size))) == NULL ) {
return NULL;
}
// take the first bit for a vector pointing to the m_pData for each row
char* pdata = (char*)result + pointer_size;
if ((unsigned long)pdata % size) {
pdata += size - (unsigned long)pdata % size;
}
// for each row, set up the pointer to its m_pData
for (i = 0; i < rows; i++) {
result[i] = (void*)pdata;
pdata += row_size;
}
return result;
}
I would then setup your matrix using:
char** buffer = (char**)matrix2D(height, width, sizeof(char));
I would initialize the array using:
for (int i = 0; i < height; ++i)
for (int j = 0; j < width; ++j)
buffer[i][j] = ' ';
and I would print the array using:
for (int i = 0; i < height; ++i) {
for (int j = 0; j < width; ++j)
cout << buffer[i][j];
cout << endl;
}
You don't need to use the vector<vector<char> >::iterator. The vector class has overloaded for you the subscript operator[]. So you can write:
for(size_t i = 0; i < height; i++)
{
for(size_t j = 0; j < width; j++)
{
cout << buffer[i][j]; // buffer is a vector<vector<char> >
}
cout << "\n";
}