I am trying to read the pixel values of an image contained in a DICOM file in my simple c++ application using the Grassroots DICOM (GDCM) library. When reading the file metadata I get the following information about the picture:
Bits allocated: 16
Bits Stored: 16
High Bit: 15
Unsigned or signed: 1
Samples pr pixel: 1
Dimensions: 2
Dimension values: 256x256
Pixel Representation: 1
SamplesPerPixel: 1
ScalarType: INT16
PhotometricInterpretation: MONOCHROME2
Pixel buffer length: 131072
Given that the image has a resolution of 256x256 and is of MONOCHROME2 type, I expected the pixel buffer length to be 256x256=65536 elements but it is in fact 131072 elements long.
If I use MATLAB instead to import the pixel data i get exactly 65536 values in the range of 0 - 850 where 0 is black and 850 is white.
When i look at the pixel buffer i get from the GDCM readout in my c++ application the pixelbuffer is 131072 elements where every even indexed element is in the range -128 to +127 and every odd indexed element is in the range 0-3. like this:
Exerpt:
PixelBuffer[120] = -35
PixelBuffer[121] = 0
PixelBuffer[122] = 51
PixelBuffer[123] = 2
PixelBuffer[124] = 71
PixelBuffer[125] = 2
PixelBuffer[126] = 9
PixelBuffer[127] = 2
PixelBuffer[128] = -80
PixelBuffer[129] = 2
PixelBuffer[130] = 87
PixelBuffer[131] = 3
PixelBuffer[132] = 121
PixelBuffer[133] = 3
PixelBuffer[134] = -27
PixelBuffer[135] = 2
PixelBuffer[136] = 27
PixelBuffer[137] = 2
PixelBuffer[138] = -111
PixelBuffer[139] = 1
PixelBuffer[140] = 75
PixelBuffer[141] = 1
PixelBuffer[142] = 103
What does this arrangement of values mean? Is this some kind of typical pixel representation for monochrome images? I have been "googeling image pixel structure" and similar but cant find what I am looking for. Is there some resource available that can help me understand this arrangement of values and how they correlate to each pixel?
I use this code to read 16 bit MONOCHROME2 Dicom file:
byte[] signedData = new byte[2];
List<int> tempInt = new List<int>();
List<ushort> returnValue = new List<ushort>();
for (i = 0; i < PixelBuffer.Length; ++i)
{
i1 = i * 2;
signedData[0] = PixelBuffer[i1];
signedData[1] = PixelBuffer[i1 + 1];
short sVal = System.BitConverter.ToInt16(signedData, 0);
int pixVal = (int)(sVal * rescaleSlope + rescaleIntercept);
tempInt.Add(pixVal);
}
int minPixVal = tempInt.Min();
SignedImage = false;
if (minPixVal < 0) SignedImage = true;
foreach (int pixel in tempInt)
{
ushort val;
if (SignedImage)
val = (ushort)(pixel - short.MinValue);
else
{
if (pixel > ushort.MaxValue) val = ushort.MaxValue;
else val = (ushort)(pixel);
}
returnValue.Add(val);
}
Related
I am trying to send the rtp packet to vlc to play h265 mp4 file i have derived the packet formation from ffmpeg source code
uint8_t nal_type = (buf[0] >> 1) & 0x3F;
/*
* create the HEVC payload header and transmit the buffer as fragmentation units (FU)
*
* 0 1
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |F| Type | LayerId | TID |
* +-------------+-----------------+
*
* F = 0
* Type = 49 (fragmentation unit (FU))
* LayerId = 0
* TID = 1
*/
s->buf[0] = 49 << 1;
s->buf[1] = 1;
/*
* create the FU header
*
* 0 1 2 3 4 5 6 7
* +-+-+-+-+-+-+-+-+
* |S|E| FuType |
* +---------------+
*
* S = variable
* E = variable
* FuType = NAL unit type
*/
s->buf[2] = nal_type;
/* set the S bit: mark as start fragment */
s->buf[2] |= 1 << 7;
but i am geting a scrambled image only like the following
all i can see is one still scrambled image.i am adding some header in the code for time stamp and other thing and i am packing the buf from 5 position excluding start code
s->buf[0] = 49 << 1;
writes to the whole byte. From your description, you would need to write only those 3 bits. I'd expect this to work:
s->buf[0] &= ~14; // 14 is 1110b. unset those bits
s->buf[0] |= 49 << 1; // 'or' in your value
you'll need the same fix for the second and third byte.
I have a colored pcd file and trying to visualize it with qt. However, when I opened the colored pcd file, I can't see the colors.
Here is my code:
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_rgb (new pcl::PointCloud<pcl::PointXYZRGB>);
pcl::PointXYZRGB point;
uint32_t rgb = (static_cast<uint32_t>(255) << 16 |
static_cast<uint32_t>(15) << 8 |
static_cast<uint32_t>(15));
QString fileName_rgba = QFileDialog::getOpenFileName(this, tr("Open File"),
"/home",
tr("Pcd Files (*.pcd)"));
filePath_rgba = fileName_rgba.toStdString();
if (pcl::io::loadPCDFile<pcl::PointXYZRGB> (filePath_rgba, *cloud_rgb) == -1) //* load the file
{
PCL_ERROR ("Couldn't read file test_pcd.pcd \n");
return (-1);
}
int pointCount = cloud_rgb->width * cloud_rgb->height;
string pointString = "Loaded " + to_string(pointCount) + " data points from " + fileName_rgba.toStdString() + "with the following fields: ";
QString dum = QString::fromStdString(pointString);
ui->pcdInfo->setText(dum);
pviz.removeAllPointClouds();
vtkSmartPointer<vtkRenderWindow> renderWindow = pviz.getRenderWindow();
ui->widget_rgba->SetRenderWindow (renderWindow);
pviz.setupInteractor (ui->widget_rgba->GetInteractor (), ui->widget_rgba->GetRenderWindow ());
pviz.getInteractorStyle ()->setKeyboardModifier (pcl::visualization::INTERACTOR_KB_MOD_SHIFT);
pviz.addPointCloud<pcl::PointXYZRGB>(cloud_rgb);
pviz.setBackgroundColor(0, 0, 0.1);
ui->widget_rgba->show();
How can I see the colored version of this pcd file?
it depends on what is defining the pcd file. assuming you have a file with a header like this:
# .PCD v0.7 - Point Cloud Data file format
VERSION 0.7
FIELDS x y z rgb
SIZE 4 4 4 4
TYPE F F F F
COUNT 1 1 1 1
then rgb means you Do have colors in the point cloud,
FIELDS x y z rgb
the size of the color is 4bytes
SIZE 4 4 4 4
and is represented as a
float TYPE F F F F
so in the data rows, take the last element,
66.873619 -91.371956 773.60254 9.8649324e-039
and read the bytes R,G,B from it, for example the float 9.8649324e-039 is represented as
00000000 01101011 01101011 01101011
^-dc ^ ^ ^
|-Red |-Green |
|-Blue
Update:
# .PCD v0.7 - Point Cloud Data file format
VERSION 0.7
FIELDS x y z rgba
label
SIZE 4 4 4 4 4
TYPE F F F U U
COUNT 1 1 1 1 1
WIDTH 191572
HEIGHT 1
VIEWPOINT 0 0 0 1 0 0 0
POINTS 191572
DATA binary
in your case U means unsigned data
represents unsigned types uint8 (unsigned char), uint16 (unsigned short), uint32 (unsigned int)
so your data
2320 2e50 4344 2076 302e 3720 2d20 506f
|---X---| |
_________ |---Y---| |
|---Z---| |
|--COLOR--|
so the color is "2d20 506f"
2d 20 50 6f
^-r
^-g
^b
^-a
so
Red = 0x2D
Green = 0x20
Blue = 0x50
Alpha = 0x6F
convert those values to int and create a QColor :)
Am working on a C++ app in Windows platform. There's a unsigned char pointer that get's bytes in decimal format.
unsigned char array[160];
This will have values like this,
array[0] = 0
array[1] = 0
array[2] = 176
array[3] = 52
array[4] = 0
array[5] = 0
array[6] = 223
array[7] = 78
array[8] = 0
array[9] = 0
array[10] = 123
array[11] = 39
array[12] = 0
array[13] = 0
array[14] = 172
array[15] = 51
.......
........
.........
and so forth...
I need to take each block of 4 bytes and then calculate its decimal value.
So for eg., for the 1st 4 bytes the combined hex value is B034. Now i need to convert this to decimal and divide by 1000.
As you see, for each 4 byte block the 1st 2 bytes are always 0. So i can ignore those and then take the last 2 bytes of that block. So from above example, it's 176 & 52.
There're many ways of doing this, but i want to do it via using bit wise operators.
Below is what i tried, but it's not working. Basically am ignoring the 1st 2 bytes of every 4 byte block.
int index = 0
for (int i = 0 ; i <= 160; i++) {
index++;
index++;
float Val = ((Array[index]<<8)+Array[index+1])/1000.0f;
index++;
}
Since you're processing the array four-by-four, I recommend that you increment i by 4 in the for loop. You can also avoid confusion after dropping the unnecessary index variable - you have i in the loop and can use it directly, no?
Another thing: Prefer bitwise OR over arithmetic addition when you're trying to "concatenate" numbers, although their outcome is identical.
for (int i = 0 ; i <= 160; i += 4) {
float val = ((array[i + 2] << 8) | array[i + 3]) / 1000.0f;
}
First of all, i <= 160 is one iteration too many.
Second, your incrementation is wrong; for index, you have
Iteration 1:
1, 2, 3
And you're combining 2 and 3 - this is correct.
Iteration 2:
4, 5, 6
And you're combining 5 and 6 - should be 6 and 7.
Iteration 3:
7, 8, 9
And you're combining 8 and 9 - should be 10 and 11.
You need to increment four times per iteration, not three.
But I think it's simpler to start looping at the first index you're interested in - 2 - and increment by 4 (the "stride") directly:
for (int i = 2; i < 160; i += 4) {
float Val = ((Array[i]<<8)+Array[i+1])/1000.0f;
}
i want to convert between char and int in c++ but i've found a problem with char to int conversion.
I did a test with two numbers, 103 and 155. 103 give me "g" in char and 155 give me "ø" and both are correct, but the problem is when i try to back chars to int: "g" give me 103 (correct) but i don't know why "ø" give me -101.
I'm using a char variable to store numbers, and "prinf("%d", char[x]);" to show back the number.
I've this test script:
#include <cstdlib>
#include <cstdio>
using namespace std;
int numero = 26523;
char *inttochar(int number) {
char *salida;
for (int j=0;j<=5;j++) {
salida[5-j] = number % 256;
printf("%d = %d = %c = %c = %d\n", 5-j, number % 256, number % 256, salida[5-j], salida[5-j]);
number = number / 256;
}
return salida;
}
int main(int argc, char** argv) {
char *texto = inttochar(numero);
for (int j=0;j<=5;j++) {
printf("%d: ", j+1);
printf("%c = %d\n", texto[j], texto[j]);
}
return 0;
}
And result is:
5 = 155 = ø = ø = -101
4 = 103 = g = g = 103
3 = 0 = = = 0
2 = 0 = = = 0
1 = 0 = = = 0
0 = 0 = = = 0
1: = 0
2: = 0
3: = 0
4: = 0
5: g = 103
6: ø = -101
With this script i want to convert a number to a base 256 char. ¿What i'm doing wrong?.
Thanks!!, and i'm sorry for my english.
Characters are signed values between -128 and 127 (on most systems). You're converting something from outside that range; the conversion to a char truncates but the bit pattern is OK. Converting the other direction puts you back into the range, and 155 isn't part of it. The bit pattern for 155 is 0x9b; to convert to a signed value you invert the bits and add one, so it becomes -0x65 which is -101 in decimal.
You can fix it with an and that strips off the extended sign bits: salida[5-j] & 0xff.
Edit: As noted in the comments your salida variable is intended to be a string but you never allocate any storage for it.
char *salida = new char[6];
char appears to be a signed type on your platform. That means 155 won't fit in it. You're getting that 155 interpreted as a 2's complement signed number, which equals -101.
I have theoretical understanding of how dilation in binary image is done.
AFAIK, If my SE (structuring element) is this
0 1
1 1.
where . represents the centre, and my image(binary is this)
0 0 0 0 0
0 1 1 0 0
0 1 0 0 0
0 1 0 0 0
0 0 0 0 0
so the result of dilation is
0 1 1 0 0
1 1 1 0 0
1 1 0 0 0
1 1 0 0 0
0 0 0 0 0
I got above result by shifting Image in 0, +1 (up) and and -1(left) direction, according to SE, and taking the union of all these three shifts.
Now, I need to figure out how to implement this in C, C++.
I am not sure how to begin and how to take the union of sets.
I thought of representing original image,three shifted images and final image obtained by taking union; all using matrix.
Is there any place where I can get some sample solution to start with or any ideas to proceed ?
Thanks.
There are tons of sample implementations out there.. Google is your friend :)
EDIT
The following is a pseudo-code of the process (very similar to doing a convolution in 2D). Im sure there are more clever way to doing it:
// grayscale image, binary mask
void morph(inImage, outImage, kernel, type) {
// half size of the kernel, kernel size is n*n (easier if n is odd)
sz = (kernel.n - 1 ) / 2;
for X in inImage.rows {
for Y in inImage.cols {
if ( isOnBoundary(X,Y, inImage, sz) ) {
// check if pixel (X,Y) for boundary cases and deal with it (copy pixel as is)
// must consider half size of the kernel
val = inImage(X,Y); // quick fix
}
else {
list = [];
// get the neighborhood of this pixel (X,Y)
for I in kernel.n {
for J in kernel.n {
if ( kernel(I,J) == 1 ) {
list.add( inImage(X+I-sz, Y+J-sz) );
}
}
}
if type == dilation {
// dilation: set to one if any 1 is present, zero otherwise
val = max(list);
} else if type == erosion {
// erosion: set to zero if any 0 is present, one otherwise
val = min(list);
}
}
// set output image pixel
outImage(X,Y) = val;
}
}
}
The above code is based on this tutorial (check the source code at the end of the page).
EDIT2:
list.add( inImage(X+I-sz, Y+J-sz) );
The idea is that we want to superimpose the kernel mask (of size nxn) centered at sz (half size of mask) on the current image pixel located at (X,Y), and then just get the intensities of the pixels where the mask value is one (we are adding them to a list). Once extracted all the neighbors for that pixel, we set the output image pixel to the maximum of that list (max intensity) for dilation, and min for erosion (of course this only work for grayscale images and binary mask)
The indices of both X/Y and I/J in the statement above are assumed to start from 0.
If you prefer, you can always rewrite the indices of I/J in terms of half the size of the mask (from -sz to +sz) with a small change (the way the tutorial I linked to is using)...
Example:
Consider this 3x3 kernel mask placed and centered on pixel (X,Y), and see how we traverse the neighborhood around it:
--------------------
| | | | sz = 1;
-------------------- for (I=0 ; I<3 ; ++I)
| | (X,Y) | | for (J=0 ; J<3 ; ++J)
-------------------- vect.push_back( inImage.getPixel(X+I-sz, Y+J-sz) );
| | | |
--------------------
Perhaps a better way to look at it is how to produce an output pixel of the dilation. For the corresponding pixel in the image, align the structuring element such that the origin of the structuring element is at that image pixel. If there is any overlap, set the dilation output pixel at that location to 1, otherwise set it to 0.
So this can be done by simply looping over each pixel in the image and testing whether or not the properly shifted structuring element overlaps with the image. This means you'll probably have 4 nested loops: x img, y img, x se, y se. So for each image pixel, you loop over the pixels of the structuring element and see if there is any overlap. This may not be the most efficient algorithm, but it is probably the most straightforward.
Also, I think your example is incorrect. The dilation depends on the origin of the structuring element. If the origin is...
at the top left zero: you need to shift the image (-1,-1), (-1,0), and (0,-1) giving:
1 1 1 0 0
1 1 0 0 0
1 1 0 0 0
1 0 0 0 0
0 0 0 0 0
at the bottom right: you need to shift the image (0,0), (1,0), and (0,1) giving:
0 0 0 0 0
0 1 1 1 0
0 1 1 0 0
0 1 1 0 0
0 1 0 0 0
MATLAB uses floor((size(SE)+1)/2) as the origin of the SE so in this case, it will use the top left pixel of the SE. You can verify this using the imdilate MATLAB function.
OpenCV
Example: Erosion and Dilation
/* structure of the image variable
* variable n stores the order of the square matrix */
typedef struct image{
int mat[][];
int n;
}image;
/* function recieves image "to dilate" and returns "dilated"*
* structuring element predefined:
* 0 1 0
* 1 1 1
* 0 1 0
*/
image* dilate(image* to_dilate)
{
int i,j;
int does_order_increase;
image* dilated;
dilated = (image*)malloc(sizeof(image));
does_order_increase = 0;
/* checking whether there are any 1's on d border*/
for( i = 0 ; i<to_dilate->n ; i++ )
{
if( (to_dilate->a[0][i] == 1)||(to_dilate->a[i][0] == 1)||(to_dilate->a[n-1][i] == 1)||(to_dilate->a[i][n-1] == 1) )
{
does_order_increase = 1;
break;
}
}
/* size of dilated image initialized */
if( does_order_increase == 1)
dilated->n = to_dilate->n + 1;
else
dilated->n = to_dilate->n;
/* dilating image by checking every element of to_dilate and filling dilated *
* does_order_increase serves to cope with adjustments if dilated 's order increase */
for( i = 0 ; i<to_dilate->n ; i++ )
{
for( j = 0 ; j<to_dilate->n ; j++ )
{
if( to_dilate->a[i][j] == 1)
{
dilated->a[i + does_order_increase][j + does_order_increase] = 1;
dilated->a[i + does_order_increase -1][j + does_order_increase ] = 1;
dilated->a[i + does_order_increase ][j + does_order_increase -1] = 1;
dilated->a[i + does_order_increase +1][j + does_order_increase ] = 1;
dilated->a[i + does_order_increase ][j + does_order_increase +1] = 1;
}
}
}
/* dilated stores dilated binary image */
return dilated;
}
/* end of dilation */