difference between old and new cameras
Closed this issue Β· 10 comments
I am uploading cine headers of our old camera and new camera.
new_camera.txt
old_camera.txt
The frames from the old camera are dark but with proper adjustments I could visualize it using PIMS exactly like Cine Viewer (CV) software. But I cant do it with the new camera cine files as the frames are surprisingly too bright and even clipped sometimes that I need to dim the contrast/gamma. Both of the videos from old and new cameras can be load flawlessly by CV. So, I guess the issue is with PIMS reading the headers to parse frame pixels?
I appreciate your time.
For the "new" file, the Phantom software was set to record 10 bits of greyscale per pixel, but stored as 16 bits. I'm not sure pims has code to handle that situation and properly discard the unused 6 bits. It's possible that the extra 6 bits are padded in some weird way. Have you tried checking histograms of the grey values? e.g.
from matplotlib import pyplot as pl
seq = pims.open('xxx.cine')
pl.hist(seq[0].flat)
You may find that you can subtract and/or divide some constant to recover values on a scale from 0 to 1024. Whatever works could be incorporated into PIMS, although obviously it would be best if there is a clear explanation in the Cine format documentation.
Thanks for your response. I can try the histogram but not sure if that can help. I don't have two cameras' data of the same frame. Maybe I email a few frames of those videos to you? So you figure it out and update PIMS?
The images don't need to be the same β you should see a big, obvious difference in the histograms. You could also look at the min() and max() values. Instead of sending images you would want to send the raw data as a numpy array, for instance with numpy.save()
. But I'm not sure when I will get a chance to look at them.
You are right:
# Open the .cine files using pims
old_seq = pims.open(old_video)
new_seq = pims.open(new_video)
# Calculate the bin range based on the pixel intensity range
old_min, old_max = old_seq[0].min(), old_seq[0].max()
new_min, new_max = new_seq[0].min(), new_seq[0].max()
# Create subplots
fig, axes = plt.subplots(2, 1, figsize=(6, 5))
axes = np.array([axes]).reshape(2, 1)
# Plot histograms of the first frame of each sequence in subplots
axes[0, 0].hist(old_seq[0].flat, bins=np.arange(
old_min, old_max + 2) - 0.5, alpha=0.7, color='blue')
axes[0, 0].set_title('Old Camera')
axes[0, 0].set_xlabel('Pixel Intensity')
axes[0, 0].set_ylabel('Frequency')
axes[1, 0].hist(new_seq[0].flat, bins=np.arange(
new_min, new_max + 2) - 0.5, alpha=0.7, color='green')
axes[1, 0].set_title('New Camera')
axes[1, 0].set_xlabel('Pixel Intensity')
axes[1, 0].set_ylabel('Frequency')
# Adjust layout and display the plot
plt.tight_layout()
plt.show()
Resulted in:
I found a copy of the Cine format documentation. It looks like in the header, biCompression == 256
means that this file is in "RAW Packed" format, meaning that 4 10-bit values are stored in 5 bytes. So the pixel values cross byte boundaries. You may find that the image read by PIMS has a different number of pixels than expected, or has junk data at the top or bottom. Decoding the bits is possible in Python but it is not simply a matter of multiplying or dividing; someone would want to start by looking at the struct
package. Otherwise you are better off using the SDK or Cine Viewer. In the future, I believe PCC can save files in a not-packed format, which PIMS should be able to read.
Also, if you have a small (several MB) cine file in this format, please share it!
I will crop those videos and email them to you asap.
AFAICT, PIMS is reading the "packed" file correctly β Tom Caswell managed to write this code without actually having an example of a packed file :). So your problem may just be how you are interpreting/plotting the image. When I do plt.imshow(seq[0], cmap=plt.cm.gray)
on my Mac, matplotlib automatically picks the colormap to match the range of the data. The resulting image looks pretty normal to meβ¦
It sounds like this is an issue with how the pixel values are displayed. I get a similar-looking result with
plt.imshow(seq[0], cmap=plt.cm.gray, vmin=0, vmax=512)
i.e. mapping the lower half of the sensor's range to the gray values on your monitor. In other words, 1 of the 10 bits is used to extend the dynamic range of the sensor, to measure values that would have saturated the old camera.