1

I have raw image data (NEF-files) that I'm trying to process with rawpy.

My current workflow is as follows:

  1. Bad Pixel fix
  2. Calculation of white balance and brightness with a ColorChecker
  3. Definition of rawpy Parameters
  4. Postprocessing image with rawpy.postprocess(options)
  5. Saving rgb-array as tiff-file

See the code below for more details:

# bad pixel fix
raw_original = rawpy.imread('raw_image.NEF')
bad_pixels = enhance.find_bad_pixels(['raw_image.NEF'], find_hot=False)
enhance.repair_bad_pixels(raw_original, bad_pixels)
raw_repaired = raw_original


# calculation of white-balance and brightness with ColorChecker
def quick_raw(path):
    with rawpy.imread(path) as raw:
        opts = rawpy.Params(output_color=rawpy.ColorSpace.raw, four_color_rgb=True, no_auto_bright=True, 
                            user_wb=[1.0, 1.0, 1.0, 1.0], gamma=(1, 1), output_bps=8, bright=1)
        rgb_base = raw.postprocess(opts)
        raw.close()
    # mapping intensity   
    map_i = np.mean(rgb_base, axis=2).astype(float) / (2 ** 8 - 1)
    # detection of white patch of ColorChecker with thresholding
    map_i[np.logical_or(map_i <= 0.25, map_i >= 0.8)] = float('nan')
    mp_coo = np.where(~np.isnan(map_i))
    quick_rgb = rgb_base[mp_coo[0], mp_coo[1]].copy()
            
    # white balance - ratio
    avgR = np.mean(quick_rgb[..., 0])
    avgG = np.mean(quick_rgb[..., 1])
    avgB = np.mean(quick_rgb[..., 2])
    
    a = avgG / avgR
    b = avgG / avgB
    wb_mult = [a, 1, b, 1]
    
    B = 200 / avgG
    
    return wb_mult, B

wb, b = quick_raw('ColorChecker.NEF')


# defining rawpy options
opts = rawpy.Params(output_color=rawpy.ColorSpace.raw, four_color_rgb=True, no_auto_bright=True, 
                    user_wb=list(wb), gamma=(1, 1), output_bps=16, bright=b)
# postprocessing image with options
rgb = raw_repaired.postprocess(opts)
# save image as .tiff-file
cv2.imwrite('raw_image.tiff', rgb[..., ::-1])

raw_repaired.close()

To validate the process I use the same ColorChecker.NEF-file for white balance correction and as processed image. If I am correct, I should receive an image which is similar to the thumbnail I receive from Windows when opening a NEF-file. Additionaly I should receive rgb-values of (243, 243, 242) for the white patch of the ColorChecker (see https://en.wikipedia.org/wiki/ColorChecker).

Below you can see the results of my validation:

Processed tiff-image

Thumbnail of NEF-image

There's an unwanted difference between those two images and I receive (255, 255, 255) as rgb-values for the white patch which indicates that my validation basically fails.

Is there anything I'm missing in my workflow or do I perform raw image-processing in a wrong way?

Do I validate my workflow correctly? Any help is highly appreciated!

Fred
  • 11
  • 1
  • Did you look at the result of detecting the white patch? It makes no sense to me that you use all pixels with an average intensity between 0.25 and 0.8. You should instead detect the grid of the color checker and then pick the pixels in the lower-left square. A cheap method is to find the compact group of pixels with a value closest to [255,255,255]. – Cris Luengo Jul 27 '22 at 13:27
  • Since the intensity values after the first linear postprocessing of the ColorChecker are very low, the white field is detected very well by the lower threshold of 0.25. I plotted a histogramm of the intensity distribution and used it to determine the lower threshold. For verification I colored the detected pixels red and got exactly the white field. So I think the white patch detection should be fine. – Fred Jul 29 '22 at 08:25

1 Answers1

0

The .tiff you are creating is a linear tiff. It does not have a gamma curve applied to the image data. However, the thumbnail of the raw has one - it is jpg-encoded. That causes the difference you noticed.