1

I am trying to import a Nikon '.NEF' file into OpenCV. '.NEF' is the file extension for a RAW file format for pictures captured by Nikon cameras. When I open the file in Preview on a Mac, I see that the resolution is 6000 by 4000, and the picture is extremely clear. However, when I import it into OpenCV, I see only 120 by 160 (by 3 for RGB channels) data points, and this leads to a big loss in resolution.

My understanding is that there are 120 by 160 pixels in the NumPy array storing the information about pixels for OpenCV. I tried using -1 for the IMREAD_UNCHANGED flag, but many pixels were left out and image quality was greatly affected.

For your reference, here is my code:

# first Jupyter block
img = cv2.imread('DSC_1051.NEF', -1)
img.shape

Performing img.shape returns (120, 160, 3).

# second Jupyter block
cv2.namedWindow("Resize", cv2.WINDOW_NORMAL)
cv2.resizeWindow("Resize", 1000, 700)
  
# Displaying the image
cv2.imshow("Resize", img)

cv2.waitKey(0)
cv2.destroyAllWindows()

Summary of problem:

  • Original image shape is (6000, 4000)
  • Open CV imports (120, 160), leading to a big loss in resolution
  • Using the IMREAD_UNCHANGED flag did not lead to OpenCV importing all the pixels in the image, leading to a loss in quality of the image upon performing cv2.imshow().

My question: how can I use OpenCV to import the desired number of pixels? Is there a specific function that I can use? Am I missing an argument to be passed?

Christoph Rackwitz
  • 11,317
  • 4
  • 27
  • 36
  • I didn't even know OpenCV could handle such exotic file formats! does the 160x120 result even resemble what you expect to be in the file? sounds like OpenCV extracts some **thumbnail stored in the file**, which is possible if the thumbnail is a common file format simply embedded. those can often be recovered from arbitrary byte streams. – Christoph Rackwitz Feb 15 '23 at 08:33
  • Yes, it does resemble what is in the file, but the resolution is really bad. – ganeshravisankar Feb 15 '23 at 19:19
  • @ChristophRackwitz I see what you mean. I think what you suggested might be the case - OpenCV probably just imports the thumbnail. In fact, the pixel sizes themselves may actually match! – ganeshravisankar Feb 17 '23 at 02:29

1 Answers1

5

If you want to manipulate RAW images without losing resolution with python you'd need to check on a specialized library like rawpy

import rawpy

with rawpy.imread('filename.NEF') as raw:
    raw_image = raw.raw_image

You can check the rawpy documentation for more information

Notes:

  • To install rawpy, Python<=3.7 is required
  • If you explain a little bit more what do u need to do with the image I could help you with that

Example 1: how to save .NEF as .jpg

Option A: rawpy + Pillow (you need to install Pillow too)

import rawpy
from PIL import Image

with rawpy.imread('filename.NEF') as raw:
    rgb = raw.postprocess(use_camera_wb=True)
    Image.fromarray(rgb).save('image.jpg', quality=90, optimize=True)

Option B: rawpy + cv2

import rawpy
import cv2

with rawpy.imread('filename.NEF') as raw:
    rgb = raw.postprocess(use_camera_wb=True)
    bgr = cv2.cvtColor(rgb, cv2.COLOR_RGB2BGR)
    cv2.imwrite("image.jpg",bgr)

Quality comparison

I test the code with this 19.2mb .NEF image and I got these results:

Method .jpg output size Dimensions
PIL 9kb 320x212
cv2 14kb 320x212
rawpy + PIL 1.4mb 4284 × 2844
rawpy + cv2 2.5mb 4284 × 2844

Example 2: show .NEF with cv2

import rawpy
import cv2

with rawpy.imread('filename.NEF') as raw:
    rgb = raw.postprocess(use_camera_wb=True)
    bgr = cv2.cvtColor(rgb, cv2.COLOR_RGB2BGR)

    cv2.imshow('image', bgr)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
Pedro Rocha
  • 1,373
  • 1
  • 3
  • 14