3

I have read several JP2 (JPEG200) images with matplotlib and got numpy arrays with big numbers, exceeding 40000.

Reading code:

img_blue =mpimg.imread('B02.jp2')
img_green =mpimg.imread('B03.jp2')
img_red =mpimg.imread('B04.jp2')

Data is:

[[12290 12694 13034 ...,  1968  2078  2118]
 [12174 12374 12696 ...,  1998  2068  2134]
 [12422 12522 12512 ...,  1990  1972  1990]
 ..., 
 [ 4268  4276  4064 ...,     0     0     0]
 [ 4174  4114  3938 ...,     0     0     0]
 [ 3954  4036  3906 ...,     

What does this data mean?

Does it mean JP2 can contain larger dynamic range? How can I convert it to normal image? Just normalize? What is denominator?

Example of file is here: http://sentinel-s2-l1c.s3.amazonaws.com/tiles/37/U/DB/2017/5/10/0/B02.jp2

Dims
  • 47,675
  • 117
  • 331
  • 600

3 Answers3

4

Question: Does it mean JP2 can contain larger dynamic range?

Yes, it does:

JPEG 2000 supports any bit depth, such as 16- and 32-bit floating point pixel images, and any color space.


Question: How can I convert it to normal image? Just normalize? What is denominator?

An HDR image must be mapped to an 8-bit image through tonemapping which, in general, is a non-linear mapping. Different tonemapping curves will produce different results. You can do it with OpenCV as shown in the OpenCV tutorial on HDR image processing:

# Play with the gamma value to arrive at a result that you like
tonemap = cv2.createTonemapDurand(gamma=2.2)
tonemapped_img = tonemap.process(img.copy())
img_8bit = numpy.clip(tonemapped_img*255, 0, 255).astype('uint8')
Leon
  • 31,443
  • 4
  • 72
  • 97
  • How can euristic "playing" with gamma be better than just normalizing? I understand something can be nonlinear, but what is the curve? It should be defined, otherwise norm looks better. Am I wrong? – Dims May 22 '17 at 20:49
  • @Dims Suppose that 99% of your pixels are within the normal 8-bit range (0-255) while 1% exceed 40000. Normalizing the largest value to 255 (white) will turn the 99% percent of the image to black. With a nonlinear tonemapping curve you can arrive at an image with various shades of gray. – Leon May 23 '17 at 06:28
  • I understand this, but why would my histogram have such properties? Is this because some standarts? Or this is because object nature? Suppose that you have such properties in normal JPEG. For example, you scanned big white paper with small black letter in the center. Why would I remap color if this is the true situation? – Dims May 24 '17 at 11:38
  • 1
    Please read https://en.wikipedia.org/wiki/Tone_mapping. An excerpt therein explains why I cannot answer all your questions without knowing the requirements of your application: *The goals of tone mapping can be differently stated depending on the particular application. In some cases producing just aesthetically pleasing images is the main goal, while other applications might emphasize reproducing as many image details as possible, or maximizing the image contrast. The goal in realistic rendering applications might be to obtain a perceptual match between a real scene and a displayed image ...* – Leon May 24 '17 at 12:13
  • If I wanted to map the RGB values of this JP2 to [0 1], should I follow the same procedure? – Vahni Jun 22 '18 at 06:16
0

I just divide 22.5 to B02,B03,B04 and combine it.

saw this page https://knowledge.safe.com/articles/43742/making-rgb-images-with-sentinel-data.html

my code is

b_r = im_b_04/22.5;
b_g = im_b_03/22.5;
b_b = im_b_02/22.5;

RGB_gt = numpy.zeros([len(b_r), len(b_r[0]), 3], np.uint8)
RGB_gt[:, :, 0] = b_r;
RGB_gt[:, :, 1] = b_g;
RGB_gt[:, :, 2] = b_b;

it works.

  • Hi @Jiwon_Hwang, i would like to know why do you use that particular value (33.5) for the division operation? I could not find where it comes from. – Bayes Aug 18 '19 at 15:08
0
import rasterio

ds = rasterio.open(path_to_jp2_image)
ds.read(1)

see: can't open jp2 (from sentinel) with python rasterio,gdal