最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

python - OpenCV: Saving image files - Difference between cv.imwrite and f.write()? - Stack Overflow

programmeradmin2浏览0评论

I'm importing images from a security camera for image processing. After importing the image, I want to save the image for archiving (processing will happen on the fly).

I see two available methods for doing so:

  • Python's built in file writer (which I will refer to as the "file method")
  • OpenCV's imwrite (which I will refer to as the "OpenCV method"), which requires me to decode the image using NumPy

During testing using the code below, I found the following results:

  • OpenCV method file (292 KB) is considerably larger than the file method's file (153 KB)
  • Values such as dpi (96), bit depth (24) and pixel resolution (1920x1080) are identical between the files
  • The file method's file contains more metadata, such as creation time, color representation and camera info (see screenshot ), likely due to NumPy/OpenCV not passing this data on.

Thus, my question is: Which method is better? I want to retain as much information as possible. Why is there such a disparity between the images?

import requests
import numpy as np
import cv2 as cv

response = requests.get(cam_url, auth=login)
image = cv.imdecode(np.frombuffer(response.content, dtype=np.uint8), -1)

with open('file_method.jpg', 'wb') as f:
    f.write(response.content)

cv.imwrite('opencv_method.jpg', image)

N.B.:

  • I cannot link the snapshots themselves for privacy reasons. But trust me, there's no discernable difference between the two.
  • I am aware that using PNG files is preferred over JPEG, but that's beside the point here).

System info:

  • Python 3.12.7
  • OpenCV 4.10.0
  • NumPy 2.1.3
  • WSL2 (Ubuntu 22.04.5 LTS (GNU/Linux 5.15.167.4-microsoft-standard-WSL2 x86_64)

EDIT:

Conclusion (summary of the kind comments below):

  • The first method saves the raw file directly, the second encodes it (NumPy) then decodes it (OpenCV) and then saves it.
  • The encoding / decoding process strips the image of its EXIF metadata.
  • The difference in file size is likely due to greater compatibility of the re-encoded version, which in my case is redundant.
  • The first method results in a smaller file with EXIF data included, albeit with the constraint that the output image format needs to be the same as the input. The second method is "safer", allowing the user to choose the output format.

EXIF Info (from ExifTool):

File Method

    ExifTool Version Number         : 12.40
    File Name                       : file_method.jpg
    Directory                       : .
    File Size                       : 153 KiB
    File Modification Date/Time     : 2025:01:20 11:26:40+01:00
    File Access Date/Time           : 2025:01:20 11:44:37+01:00
    File Inode Change Date/Time     : 2025:01:20 11:44:31+01:00
    File Permissions                : -rw-r--r--
    File Type                       : JPEG
    File Type Extension             : jpg
    MIME Type                       : image/jpeg
    JFIF Version                    : 1.02
    Resolution Unit                 : None
    X Resolution                    : 1
    Y Resolution                    : 1
    Exif Byte Order                 : Little-endian (Intel, II)
    Make                            : AXIS
    Camera Model Name               : P1455-LE
    Software                        : 10.4.5
    Modify Date                     : 2025:01:20 11:16:51
    Exposure Time                   : 1/82
    F Number                        : 429496729.5
    ISO                             : 65535
    Sensitivity Type                : Unknown
    Time Zone Offset                : 1
    Exif Version                    : 0231
    Date/Time Original              : 2025:01:20 11:16:51
    Create Date                     : 2025:01:20 11:16:51
    Sub Sec Time Original           : 987
    Sub Sec Time Digitized          : 987
    Flashpix Version                : 0100
    Color Space                     : sRGB
    Exposure Mode                   : Auto
    Serial Number                   : B8A44F0C0631
    Comment                         : ..g�"�bg�"�b.
    Image Width                     : 1920
    Image Height                    : 1080
    Encoding Process                : Baseline DCT, Huffman coding
    Bits Per Sample                 : 8
    Color Components                : 3
    Y Cb Cr Sub Sampling            : YCbCr4:2:0 (2 2)
    Aperture                        : 429496729.5
    Image Size                      : 1920x1080
    Megapixels                      : 2.1
    Shutter Speed                   : 1/82
    Create Date                     : 2025:01:20 11:16:51.987
    Date/Time Original              : 2025:01:20 11:16:51.987
    Light Value                     : 54.4

OpenCV Method

    ExifTool Version Number         : 12.40
    File Name                       : opencv_file.jpg
    Directory                       : .
    File Size                       : 292 KiB
    File Modification Date/Time     : 2025:01:20 11:13:20+01:00
    File Access Date/Time           : 2025:01:20 11:26:58+01:00
    File Inode Change Date/Time     : 2025:01:20 11:13:20+01:00
    File Permissions                : -rw-r--r--
    File Type                       : JPEG
    File Type Extension             : jpg
    MIME Type                       : image/jpeg
    JFIF Version                    : 1.01
    Resolution Unit                 : None
    X Resolution                    : 1
    Y Resolution                    : 1
    Image Width                     : 1920
    Image Height                    : 1080
    Encoding Process                : Baseline DCT, Huffman coding
    Bits Per Sample                 : 8
    Color Components                : 3
    Y Cb Cr Sub Sampling            : YCbCr4:2:0 (2 2)
    Image Size                      : 1920x1080
    Megapixels                      : 2.1

I'm importing images from a security camera for image processing. After importing the image, I want to save the image for archiving (processing will happen on the fly).

I see two available methods for doing so:

  • Python's built in file writer (which I will refer to as the "file method")
  • OpenCV's imwrite (which I will refer to as the "OpenCV method"), which requires me to decode the image using NumPy

During testing using the code below, I found the following results:

  • OpenCV method file (292 KB) is considerably larger than the file method's file (153 KB)
  • Values such as dpi (96), bit depth (24) and pixel resolution (1920x1080) are identical between the files
  • The file method's file contains more metadata, such as creation time, color representation and camera info (see screenshot ), likely due to NumPy/OpenCV not passing this data on.

Thus, my question is: Which method is better? I want to retain as much information as possible. Why is there such a disparity between the images?

import requests
import numpy as np
import cv2 as cv

response = requests.get(cam_url, auth=login)
image = cv.imdecode(np.frombuffer(response.content, dtype=np.uint8), -1)

with open('file_method.jpg', 'wb') as f:
    f.write(response.content)

cv.imwrite('opencv_method.jpg', image)

N.B.:

  • I cannot link the snapshots themselves for privacy reasons. But trust me, there's no discernable difference between the two.
  • I am aware that using PNG files is preferred over JPEG, but that's beside the point here).

System info:

  • Python 3.12.7
  • OpenCV 4.10.0
  • NumPy 2.1.3
  • WSL2 (Ubuntu 22.04.5 LTS (GNU/Linux 5.15.167.4-microsoft-standard-WSL2 x86_64)

EDIT:

Conclusion (summary of the kind comments below):

  • The first method saves the raw file directly, the second encodes it (NumPy) then decodes it (OpenCV) and then saves it.
  • The encoding / decoding process strips the image of its EXIF metadata.
  • The difference in file size is likely due to greater compatibility of the re-encoded version, which in my case is redundant.
  • The first method results in a smaller file with EXIF data included, albeit with the constraint that the output image format needs to be the same as the input. The second method is "safer", allowing the user to choose the output format.

EXIF Info (from ExifTool):

File Method

    ExifTool Version Number         : 12.40
    File Name                       : file_method.jpg
    Directory                       : .
    File Size                       : 153 KiB
    File Modification Date/Time     : 2025:01:20 11:26:40+01:00
    File Access Date/Time           : 2025:01:20 11:44:37+01:00
    File Inode Change Date/Time     : 2025:01:20 11:44:31+01:00
    File Permissions                : -rw-r--r--
    File Type                       : JPEG
    File Type Extension             : jpg
    MIME Type                       : image/jpeg
    JFIF Version                    : 1.02
    Resolution Unit                 : None
    X Resolution                    : 1
    Y Resolution                    : 1
    Exif Byte Order                 : Little-endian (Intel, II)
    Make                            : AXIS
    Camera Model Name               : P1455-LE
    Software                        : 10.4.5
    Modify Date                     : 2025:01:20 11:16:51
    Exposure Time                   : 1/82
    F Number                        : 429496729.5
    ISO                             : 65535
    Sensitivity Type                : Unknown
    Time Zone Offset                : 1
    Exif Version                    : 0231
    Date/Time Original              : 2025:01:20 11:16:51
    Create Date                     : 2025:01:20 11:16:51
    Sub Sec Time Original           : 987
    Sub Sec Time Digitized          : 987
    Flashpix Version                : 0100
    Color Space                     : sRGB
    Exposure Mode                   : Auto
    Serial Number                   : B8A44F0C0631
    Comment                         : ..g�"�bg�"�b.
    Image Width                     : 1920
    Image Height                    : 1080
    Encoding Process                : Baseline DCT, Huffman coding
    Bits Per Sample                 : 8
    Color Components                : 3
    Y Cb Cr Sub Sampling            : YCbCr4:2:0 (2 2)
    Aperture                        : 429496729.5
    Image Size                      : 1920x1080
    Megapixels                      : 2.1
    Shutter Speed                   : 1/82
    Create Date                     : 2025:01:20 11:16:51.987
    Date/Time Original              : 2025:01:20 11:16:51.987
    Light Value                     : 54.4

OpenCV Method

    ExifTool Version Number         : 12.40
    File Name                       : opencv_file.jpg
    Directory                       : .
    File Size                       : 292 KiB
    File Modification Date/Time     : 2025:01:20 11:13:20+01:00
    File Access Date/Time           : 2025:01:20 11:26:58+01:00
    File Inode Change Date/Time     : 2025:01:20 11:13:20+01:00
    File Permissions                : -rw-r--r--
    File Type                       : JPEG
    File Type Extension             : jpg
    MIME Type                       : image/jpeg
    JFIF Version                    : 1.01
    Resolution Unit                 : None
    X Resolution                    : 1
    Y Resolution                    : 1
    Image Width                     : 1920
    Image Height                    : 1080
    Encoding Process                : Baseline DCT, Huffman coding
    Bits Per Sample                 : 8
    Color Components                : 3
    Y Cb Cr Sub Sampling            : YCbCr4:2:0 (2 2)
    Image Size                      : 1920x1080
    Megapixels                      : 2.1
Share Improve this question edited Jan 21 at 22:02 Christoph Rackwitz 15.4k5 gold badges39 silver badges51 bronze badges asked Jan 20 at 11:00 OaknutOaknut 136 bronze badges 8
  • 1 Run exiftool IMAGENAME on each file to see the differences in size, compression, quality, colourspace, metadata etc. Click edit and add the output to your question if you cannot see the critical differences - don't put results in a comment. – Mark Setchell Commented Jan 20 at 11:18
  • Those are completely different functions. f.write just write data whatever they are. Which, in your case (seemingly) happens to be jpg data, so an image file. When imwrite does create an image (encode into jpg or png or ...). – chrslg Commented Jan 20 at 11:46
  • If all what you do with the image you get is to save them, and if you can trust the fact that they will always be in jpg format (as you assume they are by saving them under a .jpg name), then, obviously, the first method is the better: you have a jpg file in memory, you want to have it on disk, just write it indeed (why decode the file, then reencode it? decoding/encoding cannot gain anythning. If you use bigger bitrate, the file is bigger, but quality isn't, since of course, quality of an image cannot be improved. If bitrate is smaller, quality is also smaller) – chrslg Commented Jan 20 at 11:49
  • Now, as I understand, the program will also do some processing on the image. So you will decode the image in a numpy array anyway. So, writing the jpg as received from the server only spare the reencoding, but not the decoding. There might be some other reason why you could want to reencode and save the image you've decoded (imwrite) rather than saving the raw data before decoding (write). For example, you may want to add annotation to the image before saving them. Or, you may have a code that is "transparent" to the way the image are acquired – chrslg Commented Jan 20 at 11:55
  • (for example, if, instead of getting jpg images one by one from the server, you get some RTSP stream. Or the image under a different format. Using imwrite ensures that you decide which file format is used to write the image, instead of forcing you to have the exact same format as the one provided by the camera server) – chrslg Commented Jan 20 at 11:57
 |  Show 3 more comments

1 Answer 1

Reset to default 1

If, as stated, your goal is to retain as much quality as possible, you should use the write() method because it retains exactly the quality and metadata you got from the original feed.

Using cv2.imwrite() will definitely lose metadata and any attached colour profiles and also risks either losing quality, or adding unnecessary bloat but it cannot improve the quality.


The reason the two are different is most likely due to a different JPEG quality setting. You can explore the parameters of the original vs OpenCV-saved image with:

exiftool YOURIMAGE

Or, in a more targeted way, with:

exiftool -filesize -JPEGQualityEstimate -n YOURIMAGE

Output will look similar to this:

File Size                       : 292000
JPEG Quality Estimate           : 75
发布评论

评论列表(0)

  1. 暂无评论