【问题标题】:Convert .IMG (Classic Disk Image) to .PNG/.JPG in Python在 Python 中将 .IMG(经典磁盘映像)转换为 .PNG/.JPG
【发布时间】:2020-06-20 10:47:30
【问题描述】:

我有一个包含 1,00,000 多个 .IMG 文件的数据集,我需要将这些文件转换为 .PNG / .JPG 格式,以便将 CNN 应用于简单的分类任务。
我提到了this answer,该解决方案部分对我有用。我的意思是有些图像没有正确转换。其原因,据我了解,有些图像的像素深度为 16,而有些图像的像素深度为 8。

for file in fileList:
    rawData = open(file, 'rb').read()
    size = re.search("(LINES              = \d\d\d\d)|(LINES              = \d\d\d)", str(rawData))
    pixelDepth = re.search("(SAMPLE_BITS        = \d\d)|(SAMPLE_BITS        = \d)", str(rawData))
    size = (str(size)[-6:-2])
    pixelDepth = (str(pixelDepth)[-4:-2])
    print(int(size))
    print(int(pixelDepth))
    imgSize = (int(size), int(size))



    img = Image.frombytes('L', imgSize, rawData)
    img.save(str(file)+'.jpg')


数据来源:NASA Messenger Mission
.IMG files and their corresponding converted .JPG Files


像素深度为 8 的文件已成功转换:


像素深度为 16 的文件未正确转换:

如果我需要提供更多信息,请告诉我。

【问题讨论】:

  • 此外,所有图像的顶部边缘部分似乎都不正确。可能是因为 PIL 试图将文件顶部的元数据转换为图像?
  • 您只想更改图片扩展名吗?
  • @jizhihaoSAMA 我要转换图片
  • 文件 EW0220137564B.IMG 中的像素的平均值为 252,标准差仅为 3,因此该图像中没有任何有趣的东西。如果您提供更多 IMG 示例,我会仔细查看。
  • "可能是因为 PIL 试图将文件顶部的元数据转换为图像吗?"它会转换你喂它的东西,这就是设计。你有没有想过下采样到 8 位?

标签: python type-conversion png python-imaging-library jpeg


【解决方案1】:

希望通过我的另一个答案here,您现在可以更好地了解文件的格式。所以,代码应该是这样的:

#!/usr/bin/env python3

import sys
import re
import numpy as np
from PIL import Image
import cv2

rawData  = open('EW0220137564B.IMG', 'rb').read()
# File size in bytes
fs       = len(rawData)
bitDepth = int(re.search("SAMPLE_BITS\s+=\s+(\d+)",str(rawData)).group(1))
bytespp  = int(bitDepth/8)
height   = int(re.search("LINES\s+=\s+(\d+)",str(rawData)).group(1))
width    = int(re.search("LINE_SAMPLES\s+=\s+(\d+)",str(rawData)).group(1))
print(bitDepth,height,width)

# Offset from start of file to image data - assumes image at tail end of file
offset = fs - (width*height*bytespp)

# Check bitDepth
if bitDepth == 8:
    na = np.frombuffer(rawData, offset=offset, dtype=np.uint8).reshape(height,width)
elif bitDepth == 16:
    dt = np.dtype(np.uint16)
    dt = dt.newbyteorder('>')
    na = np.frombuffer(rawData, offset=offset, dtype=dt).reshape(height,width).astype(np.uint8)
else:
    print(f'ERROR: Unexpected bit depth: {bitDepth}',file=sys.stderr)

# Save either with PIL
Image.fromarray(na).save('result.jpg')
# Or with OpenCV may be faster
cv2.imwrite('result.jpg', na)

如果您有成千上万的事情要做,我会推荐 GNU Parallel,您可以使用 homebrew 轻松将其安装到您的 Mac 上:

brew install parallel

然后您可以更改我上面的程序以接受文件名作为参数代替硬编码的文件名,并且并行完成它们的命令是:

parallel --dry-run script.py {} ::: *.IMG

如果需要更多的努力,您可以通过将上面的代码放在一个函数中并为每个指定为参数的文件调用该函数来更快地完成它。这样您就可以避免为每个图像启动一个新的 Python 解释器,并告诉 GNU Parallel 将尽可能多的文件传递给脚本的每次调用,如下所示:

parallel -X --dry-run script.py ::: *.IMG

脚本的结构如下所示:

def processOne(filename):
    open, read, search, extract, save as per my code above

# Main - process all filenames received as parameters
for filename in sys.argv[1:]:
    processOne(filename)

【讨论】:

  • 非常感谢您抽出时间来写这个答案。我已经理解它并且它对我有用。
  • 太好了,不客气。祝你的项目好运,记住,问题(和答案)是免费的,所以如果你遇到困难,请回来。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-05-19
  • 2012-06-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-10
  • 2012-01-22
  • 2011-10-21
相关资源
最近更新 更多