在 Python 中将 .IMG(经典磁盘图像)转换为 .PNG/.JPG

Convert .IMG (Classic Disk Image) to .PNG/.JPG in Python

我有一个包含 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


Files with Pixel Depth of 8 are successfully converted:


Files with Pixel Depth of 16 are NOT properly converted:

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

希望通过我的另一个回答 ,您现在对文件的格式有了更好的理解。因此,代码应如下所示:

#!/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[=31= 轻松将其安装在 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)