how to assign 1D spectra to imagestack - sdk

any idea why this does not work?
DM::Image im2D = DM::RealImage("2D", 4, 2048);
DM::Image im3D= DM::RealImage("3D", 4, 2048, 9, 9);
PlugIn::ImageDataLocker im2D_LLl(im2D, PlugIn::ImageDataLocker::lock_data_CONTIGUOUS);
float *im2D_data = (float*)(im2D_LLl.get_image_data().get_data());
for (int i = 0; i <2048; i++) *Im2D_data++ = i;
Imaging::DataSlice planeSlice;
long xi=0, yi=0;
planeSlice = Imaging::DataSlice(Imaging::DataIndex(xi, yi, 0), Imaging::DataSlice::Slice1(2, 2048, 1));
DM::SliceImage(im3D, planeSlice) = im2D;
im3D is not changed, giving only zeros. In DM scripting side this would be:
slice1(im3D, 0,0,0,2,2048,1) = im2D
which works fine.

I'm somewhat confused by your example code.
It seems you create a 3D image of XYZ = 2048 x 9 x 9
but then slice it along dim=2 (z) for 2048 channels (it has only 9!)
The same is true for you script code. slice1 creates a 1D image along the dimension 2.
I think you've meant to use
slice2( img3D, 0,0,0, 0,9,1, 1,9,1 ) = img2d
Or, if you really meant to do spectrum-insertion (as you title suggests), you want some better named variables for sure.
Script example of creating a stack and filling it plane-wise:
image stack := realimage("Stack of 2048 2D images 9x9",4,9,9,2048)
for ( number i=0; i<2048; i++ ){
image plane2D := Realimage("2D plane 9x9",4,9,9)
plane2D = iradius + random()
stack.Slice2(0,0,i, 0,9,1, 1,9,1 ) = plane2D
}
stack.ShowImage()
Script example of creating a stack and filling it spectrum-wise:
image stack := realimage("Stack of 2048 2D images 9x9",4,9,9,2048)
for ( number i=0; i<9; i++ ){
for ( number j=0; j<9; j++ ){
image spec1D:= Realimage("1D spectrum 2048",4,2048)
spec1D = iradius + random()
stack.Slice1(i,j,0, 2,2048,1 ) = spec1D
}
}
stack.ShowImage()
As for the SDK code: When you create an image locker to change the data, make sure you use
im2d.DataChanged();
to finalize and update the image object.

Related

OpenCV Tone Curve progrommatically

I want to realize smth like tone curve.
I have predefined set of curves that I should apply to the image.
For instance:
as I understand on this chart we see dependences of current tone value to new, for example:
if we get first dot on the left - every r,g and b that = 0 will be converted to 64
or every value more than 224 will be converted to 0 and ect.
so I tried to change every pixel of image to new value
for test purpose i've simplified curve:
and here the code I have:
//init original image
cv::Mat originalMat = [self cvMatFromUIImage:inputImage];
//out image the same size
cv::Mat outMat = [self cvMatFromUIImage:inputImage];
//loop throw every row of image
for( int y = 0; y < originalMat.rows; y++ ){
//loop throw every column of image
for( int x = 0; x < originalMat.cols; x++ ){
//loop throw every color channel of image (R,G,B)
for( int c = 0; c < 3; c++ ){
if(originalMat.at<cv::Vec3b>(y,x)[c] <= 64)
outMat.at<cv::Vec3b>(y,x)[c] = 64 + ( originalMat.at<cv::Vec3b>(y,x)[c] ) -
( originalMat.at<cv::Vec3b>(y,x)[c] ) * 2 ;
if((originalMat.at<cv::Vec3b>(y,x)[c] > 64)&&(originalMat.at<cv::Vec3b>(y,x)[c] <= 128))
outMat.at<cv::Vec3b>(y,x)[c] = (( originalMat.at<cv::Vec3b>(y,x)[c] ) - 64 ) * 4
;
if((originalMat.at<cv::Vec3b>(y,x)[c] > 128))
outMat.at<cv::Vec3b>(y,x)[c] = ( originalMat.at<cv::Vec3b>(y,x)[c] ) + 128 -
(( originalMat.at<cv::Vec3b>(y,x)[c] ) - 128) * 3;
} //end of r,g,b loop
} //end of column loop
} //end of row loop
//send to output
return [self UIImageFromCVMat:outMat];
but here the result I get:
by some reason only 3/4 of image was processed
and it not matches with result i expected:
Update 0
thanks to #ACCurrent comment found errors in calculation(code and image updated), but still not understand why only 3/4 of images processed.
not sure that understand why 'noise' appears, hope it because of curve not smooth.
looks the way to avoid .at operation.
Update 1
original image:
You need to access the images with Vec4b
originalMat.type() is equals to 24
Your originalMat is of type 24, i.e. CV_8UC4. This means that the image has 4 channels, but you're accessing it with Vec3b as if it has only 3 channels. This explains why about 1/4 of the image is not modified.
So, simply replace every Vec3b in your code with Vec4b.

While trying to work copy Bit16 Mat, only half of it is being actually copied

So I am new to OpenCV, what I want to do is to copy elements of an bit16 matrix.
src.create(h, w, CV_16UC(channels));
dst.create(hr, wr, CV_16UC(channels));
finalDst.create(h, w, CV_16UC(channels));
memcpy(src.data, data_in, w*h*sizeof(raw_t_ubit16));
for (i = 0; i < h; i++)
{
for (j = 0; j < w; j++)
{
finalDst.data[j + i*w] = src.data[j + i*w];
}
}
memcpy(data_out, finalDst.data, h*w*sizeof(raw_t_ubit16));
However this only copies one half of the image, Ironically if I put 2*h instead of h then everything gets back to normal. But that shouldn't be so, since I am defining h to be the exact height of my image just like w is the width.
src.data - gives you (*uchar), but not (*raw_t_ubit16).
(*uchar) 8 bit.
(*raw_t_ubit16) 16 bit.
((*uchar)data)[2] - will point to 3-rd byte in array (assumes array of uchar).
((*raw_t_ubit16)data)[2] - will point to 5-th byte in array (assumes array of raw_t_ubit16).
That's why you got only a half copied.
You can write:
((raw_t_ubit16*)finalDst.data)[j + i*w] = ((raw_t_ubit16*)src.data)[j + i*w];
It should work, but better use clone() method of Mat class:
m1=m2.clone();

How to make OpenCV IplImage for 16 bit gray-data?

This code is for 8 bit data to make gray-scale IplImage.
IplImage* img_gray_resize = NULL;
img_gray_resize = cvCreateImage(cvSize(320, 256), IPL_DEPTH_8U, 1);
DWORD dwCount;
LVDS_SetDataMode(0); // o for 8 bit mode and 1 for 16 bit mode
dwCount = (LONG)320 * (LONG)256;
unsigned char* m_pImage = NULL;
m_pImage = new unsigned char[320 * 256];
for (int i=0; i<320 * 256; i++) m_pImage[i] = NULL;
LVDS_GetFrame(&dwCount, m_pImage);
int width = 320;
int height = 256;
int nn = 0;
int ii = 0;
for (int y=0; y<height; y++)
{
for (int x=0; x<width; x++)
{
ii = y * width + x;
if(nn < (height*width))
img_gray_resize->imageData[ii] = m_pImage[nn++];
}
}
delete [] m_pImage;
I need to display 16 bit gray-scale image. If I display 8 bit data, some information is missing from the image. However, LVDS_SetDataMode() can provide both types of data. I am using a library for frame grabber device. Please help me.
16 bit images should be stored in IPL_DEPTH_16U (or CV_16U) mode. This is the correct memory layout.
However, displaying them depends on your display hardware.
Most regular display APIs, e.g. OpenCV's highgui, can only display 8-bit images.
To actually display the image, you will have to convert your image to 8-bits for display.
You will need to decide how to do this. There are many ways to do this, depending on your application and complexity. Some options are:
Show MSB = right-shift the image by 8 pixels.
Show LSB = saturate anything above 255.
In fact, right-shift by any value between 0-8 bits, combined with a cv::saturate_cast to avoid value wrap-around.
HDR->LDR = Apply dynamic range compression algorithms.
as I know,only 8bit data can be displayed,you need to find the best way to convert the 16bit to 8bit to minimize the information you lose. Histogram equalization can be applyed to do this.
Finally, I have solved the problem by following way:
dwCount = (LONG)320 * (LONG)256 * 2;
LVDS_SetDataMode(1);
img_gray_resize->imageData[ii] = m_pImage[nn++] >> 6;
Just shift bits to right (2, 3, 4, 5, 6, ...), where you get good result, use that value.

Displaying histogram plot openCV

I have the histogram for an image which i have calculated. I want to display this as an image so that I can actually see the histogram. I think my problem is to do with scaling although i am slightly confused over the co ordinate system starting with 0,0 in the top left as well.
int rows = channel.rows;
int cols = channel.cols;
int hist[256] = {0};
for(int i = 0; i<rows; i++)
{
for(int k = 0; k<cols; k++ )
{
int value = channel.at<cv::Vec3b>(i,k)[0];
hist[value] = hist[value] + 1;
}
}
Mat histPlot = cvCreateMat(256, 500,CV_8UC1);
for(int i = 0; i < 256; i++)
{
int mag = hist[i];
line(histPlot,Point(i,0),Point(i,mag),Scalar(255,0,0));
}
namedWindow("Hist",1);
imshow("Hist",histPlot);
This is my calculation for creating my histogram and displaying the result. If i do mag/100 in my second loop then i get some resemblance of a plot appearing (although upside down). I call this method whenever i adjust a value of my image, so the histogram should also change shape, which it doesn't appear to do. Any help in scaling the histogram and displaying it properly is appreciated.
please don't use cvCreateMat ( aka, the old c-api ), you also seem to have rows and cols wrong, additionally, if you want a color drawing, you need a color image as well, so make that:
Mat histPlot( 500, 256, CV_8UC3 );
image origin is top-left(0,0), so you've got to put y in reverse:
line(histPlot,Point(i,histPlot.rows-1),Point(i,histPlot.rows-1-mag/100),Scalar(255,0,0));

Move every pixel to right (by 1px) in OpenCV without using remap?

I want to move every pixel in an image to right by 1px, and below is the map I use to do the remap transformation.
This approach require much more time than it should to do such a simple transform. Is there a cv function I can use? Or do I just split the image into 2 images, one is src.cols-1 pixels wide, the other is 1 px wide, and then copy them to the new image?
void update_map()
{
for( int j = 0; j < src.cols; j++ ){
for( int i = 0; i < src.rows; i++ ){
if (j == src.cols-1)
mat_x_Rotate.at<float>(i,j) = 0;
else
mat_x_Rotate.at<float>(i,j) = j + 1;
mat_y_Rotate.at<float>(i,j) = i;
}
}
}
Things you can do to improve your performance:
remap is overkill for this purpose. It is more efficient to copy the pixels directly than to define an entire remap transformation and then use it.
switch your loop order: iterate over rows, then columns. (OpenCV's Mat is stored in row-major order, so iterating over columns first is very cache-unfriendly)
use Mat::ptr() to access pixels in the same row directly, as a C-style array. (this is a big performance win over using at<>(), which probably does stuff like check indices for each access)
take your if statement out of the inner loop, and handle column 0 separately.
As an alternative: yes, splitting the image into parts and copying to the new image might be about as efficient as copying directly, as described above.
Mat Shift_Image_to_Right( Mat src_in, int num_pixels)
{
Size sz_src_in = src_in.size();
Mat img_out(sz_src_in.height, sz_src_in.width, CV_8UC3);
Rect roi;
roi.x = 0;
roi.y = 0;
roi.width = sz_src_in.width-num_pixels;
roi.height = sz_src_in.height;
Mat crop;
crop = src_in(roi);
// Move the left boundary to the right
img_out = Scalar::all(0);
img_out.adjustROI(0, 0, -num_pixels, 0);
crop.copyTo(img_out);
img_out.adjustROI(0, 0, num_pixels, 0);
return img_out;
}

Resources