I've started editing the RaspiStillYUV.c code. I eventually want to process the image I receive, but for now, I'm just working to understand it. Why am I working with YUV instead of RGB? So I can learn something new. I've made minor changes to the function camera_buffer_callback. All I am doing is the following:
fprintf(stderr, "GREAT SUCCESS! %d\n", buffer->length);
The line this is replacing:
bytes_written = fwrite(buffer->data, 1, buffer->length, pData->file_handle);
Now, the dimensions should be 2592 x 1944 (w x h) as set in the code. Working off of Wikipedia (YUV420) I have come to the conclusion that the file size should be w * h * 1.5. Since the Y component has 1 byte of data for each pixel and the U and V components have 1 byte of data for every 4 pixels (1 + 1/4 + 1/4 = 1.5). Great. Doing the math in Python:
>>> 2592 * 1944 * 1.5
7558272.0
Unfortunately, this does not line up with the output of my program:
GREAT SUCCESS! 7589376
That leaves a difference of 31104 bytes.
I figure that the buffer is allocated in fixed size chunks (the output size is evenly divisible by 512). While I would like to understand that mystery, I'm fine with the fixed size chunk explanation.
My question is if I am missing something. Are the extra bytes beyond the expected size meaningful in this format? Should they be ignored? Are my calculations off?
The documentation at this location supports your theory on padding: http://www.raspberrypi.org/wp-content/uploads/2013/07/RaspiCam-Documentation.pdf
Specifically:
Note that the image buffers saved in raspistillyuv are padded to a
horizontal size divisible by 16 (so there may be unused bytes at the
end of each line to made the width divisible by 16). Buffers are also
padded vertically to be divisible by 16, and in the YUV mode, each
plane of Y,U,V is padded in this way.
So my interpretation of this is the following.
The width is 2592 (divisible by 16 so this is ok).
The height is 1944 which is 8 short of being divisible by 16 so an extra 8*2592 are added (also multiplied by 1.5) thus giving your 31104 extra bytes.
Although this kindof helps with the size of the file, it doesn't explain the structure of the YUV output properly. I am having a look at this description to see if this provides a hint to start with: http://en.wikipedia.org/wiki/YUV#Y.27UV420p_.28and_Y.27V12_or_YV12.29_to_RGB888_conversion
From this I believe it is as follows:
Y Channel:
2592 * (1944+8) = 5059584
U Channel:
1296 * (972+4) = 1264896
V Channel:
1296 * (972+4) = 1264896
Giving a sum of :
5059584 + 2*1264896 = 7589376
This makes the numbers add up so only thing left is to confirm if this interpretation is correct.
I am also trying to do the YUV decode (for image comparisons) so if you can confirm if this actually does correspond to what you are reading in the YUV file this would be much appreciated.
You have to read the manual carefully. Buffers are padded to multiples of 16, but colour data is half-size, so your image size needs to be in multiples of 32 to avoid problems with padding breaking external software.
Related
Im chanced upon this statement while studying the allocation of RAM in embedded device.
Basically suppose we have an image sensor that uses RGB 5-6-5 format. It captures an image size of 320x240. The author proceeds to use
"There are two 150-KB data buffers that contain the raw data from the image sensor (320x240 in the
RGB 5-6-5 format). "
Does anyone know how is two 150KB data buffers enough to store the raw image? How can i calculate the image bits?
I tried calculating
( 2^5 * 2^6 * 2^5 * 320 * 240 ) * 0.000125 = 629145.6 // in KB.
You should look closer at the definition of the RGB 5:6:5 format. Each color takes up 2 bytes (5 bits for red, 6 bits for green and 5 bits for blue; adding up to 16 bits == 2 bytes), so a raw 320x240 picture takes 320 * 240 * 2 bytes, i.e. 153600 bytes or 150 KB.
I am trying to create a app that uses tensorflow model. My app crashes when inputFeature0.loadBuffer(byteBuffer) gets executed. ( got to know by commenting the lines)
var img=Bitmap.createScaledBitmap(bmp,229,229,true)
val model = SkinDiseasesDetectionFitSizeFinal24120210504.newInstance(this)
val inputFeature0 = TensorBuffer.createFixedSize(intArrayOf(1, 229, 229, 3), DataType.FLOAT32)
var tensorimage=TensorImage.fromBitmap(img)
var byteBuffer=tensorimage.buffer
inputFeature0.loadBuffer(byteBuffer)
This is the error
FATAL EXCEPTION: main
Process: com.azsky.skincancerdetection, PID: 31954
java.lang.IllegalArgumentException: The size of byte buffer and the shape do not match.
Can someone help me out in this?
in the process of converting tensorflow to TfLite if you use optimization then you should read from here first
https://www.tensorflow.org/lite/performance/post_training_quantization. it is said that the optimize version is 4 times smaller so you need to create your byte buffer to
[4 * 229 * 229 * 3] so it can match with the inputfeature0
I had same problem. I don't know why does this occurs but it is maybe because of DataType.FLOAT32. I printed both buffers and found the total size was different.
Log.d("shape", byteBuffer.toString())
Log.d("shape", inputFeature0.buffer.toString())
My inputFeature0.buffer was 4-times bigger that byteBuffer. Found it by dividing the both buffers. The solution i got from someplace it was
You should multiply your buffer with 4.
According to their explanation my buffer should be like this
buffer = image.width x image.height x colorChanels x 4
But i don't know how to change the total buffer instead is double the width and height to have the same effect.
Try using 458 x 458 image size.
I'm new to OpenGl ES. I'm trying to build a sphere not using any manuals, tutrials...
I have succeded to achieve my goal. I can draw a sphere using TRIANGLE_STRIP. And the number of meridians/horizontals I specify before drawing.
Everything works fine when I have less then 256 indexes for vertixes. I tried to use GLushort instead of GLubyte but the picture changed a lot.
GLubyte *Indices;
...
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLubyte) * (meridians * (horizontals * 2 + 2)), Indices, GL_STATIC_DRAW);
...
Indices = malloc(sizeof(GLubyte) * (meridians * (horizontals * 2 + 2)));
Thats where I change byte to short.
Current project on GitHub
What should I do?
Here are the pictures where I change byte to short
Looks like you forgot to change the following line:
glDrawElements(GL_TRIANGLE_STRIP, (meridians * (horizontals * 2 + 2)), GL_UNSIGNED_BYTE, 0);
This indicates that there are a number of indices to be render, and each one is the size of an unsigned byte (most likely 8 bits, but the actual number is platform specific...very very very rarely is it not 8 bits though). However, you have filled an array of indices that are the size of unsigned shorts (probably 16 bits) so what will end up happening is that each of your numbers will be read twice. Once with the "first" 8-bits, and once with the "second" (endian will determine whether high or low order comes first). Since a lot of your indices (the majority?) are under 255, then there are going to be a lot of vertices that turn into "0" since the higher 8 bits are all 0. On top of that, you will only render half of your indices.
So, you need to indicate to OpenGL that it needs to draw these indices as unsigned shorts instead by changing the above line to this:
glDrawElements(GL_TRIANGLE_STRIP, (meridians * (horizontals * 2 + 2)), GL_UNSIGNED_SHORT, 0);
I'm trying to read a TIFF image that has been exported from a Leica (SP5) program. I can read other details (e.g. bits per sample, image size x, image size y) as per tags defined in TIFF documentation. I'm sort of crudely reading the header out as unsigned integers until I get to a certain tag number.
I know at 296, my 'Resolution Unit' is cm. At 282 and 283, it's supposed to give me the number of pixels (in x and y) per resolution unit. I'm not sure how to do this. Can someone please help??
Well, if at 296 you discover what the unit type is (either 1 - No absolute unit, 2 - Inch, or 3 - Centimeter) and at 282 and 283 you get XResolution and YResolution respectively then you have everything you need to solve the problem.
To get a per unit type measure just multiply XResolution and YResolution together:
XResolution * YResolution = PixelsPerUnit
Since you are trying to find the area of the rectangle created by the resolutions.
I want to know how much data can be embedded into an image of different sizes.
For example in 30kb image file how much data can be stored without distortion of the image.
it depends on the image type , algoridum , if i take a example as a 24bitmap image to store ASCII character
To store a one ASCII Character = Number of Pixels / 8 (one ASCII = 8bits )
It depends on two points:
How much bits per pixel in your image.
How much bits you will embed in one pixel .
O.K lets suppose that your color model is RGB and each pixel = 8*3 bits (one byte for each color), and you want embed 3 bits in one pixel.
data that can be embedded into an image = (number of pixels * 3) bits
If you would use the LSB to hide your information this would give 30000Bits of available space to use. 3750 bytes.
As the LSB represents 1 or 0 into a byte that gets values from 0-256 this gives you in the worst case scenario that you are going to modify all the LSBs distortion of 1/256 that equals 0,4%.
In the statistical average scenario you would get 0,2% distortion.
So depends on which bit of the byte you are going to change.