python 如何将十六进制的原始字节转换为RGB图像

hpcdzsge  于 2023-01-29  发布在  Python
关注(0)|答案(1)|浏览(320)

我试图通过探索使用机器学习检测恶意软件的行为来弄脏我的手。
所以我在Kaggle上偶然发现了一个微软Big 2015数据集。这个数据集包含十六进制形式的字节数据。

00401000 00 00 80 40 40 28 00 1C 02 42 00 C4 00 20 04 20
00401010 00 00 20 09 2A 02 00 00 00 00 8E 10 41 0A 21 01
00401020 40 00 02 01 00 90 21 00 32 40 00 1C 01 40 C8 18
00582FF0 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??

指向完整字节和从字节生成的灰度图像的链接。
hexadecimal bytes

我想用python把这个十六进制字节转换成RGB图像。
这是一个脚本,将这个字节转换为灰度图像,我想复制一个RGB图像。

import sys
import os
from math import log
import numpy as np
import scipy as sp
from PIL import Image
import matplotlib.pyplot as plt
def saveimg(array,name):
    if array.shape[1]!=16:
        assert(False)
    
    b=int((array.shape[0]*16)**(0.5))
    b=2**(int(log(b)/log(2))+1)
    a=int(array.shape[0]*16/b)
    # #print a,b,array.shape
    array=array[:int(a*b/16),:]
    array=np.reshape(array,(a,b))
    print(array.shape)
    im = Image.fromarray(np.uint8(array))
    im.save(name+'.jpg', "JPEG")

path = bytes_folder # "/test/0ACDbR5M3ZhBJajygTuf.bytes"
files=os.listdir(path)
c=0
for cc,x in enumerate(files):
    if '.bytes' != x[-6:]:
        continue
    f=open(os.path.join(path,x))
    array=[]
    c+=1
    for line in f:
        xx=line.split()
        if len(xx)!=17:
            continue
        #if xx[1]=='??':
        #    break
        array.append([int(i,16) if i!='??' else 0 for i in xx[1:] ])
    saveimg(np.array(array),x)
    del array
    f.close()

'''
efzxgjgh

efzxgjgh1#

为了获得RGB图像,我们所需要的只是将数组整形为height x width x 3(应用R、G、B颜色分量的第三维必须为3)。
有许多选项可用于将任意数据转换为height x width x 3形状。
有一个重要的限制:转换前的元素总数必须等于height*width*3
示例:
我们可以定义:width = 320
则元素总数必须是320*3的倍数。
array.size不是3的倍数的情况下,我们可以删除剩余的元素。
如果我们想要正方形图像,我们可以选择:width = int((array.size / 3)**0.5).

  • 将阵列展平为1D:
array = array.ravel()
  • 从(宽度 * 3)计算余数:
remainder = array.size % (width*3)
  • 从数组末尾删除剩余元素:
if remainder > 0:
     array = array[0:-remainder]
  • 将数组重新调整为height x width x 3height是自动计算的-高度将为array.size/(320*3)
rgb_array = array.reshape((-1, width, 3))
  • 将rgb_array转换为PIL图像:
im = Image.fromarray(rgb_array, mode='RGB')

注:
这只是一个示例-有许多选项可供选择widthheight
代码示例:

import numpy as np
from PIL import Image

def conv(val):
    """ Convert val from hex string to int, return 0 if val is not a valid in hex format """
    try:
        return int(val, 16)
    except ValueError:
        return 0

# https://numpy.org/doc/stable/reference/generated/numpy.loadtxt.html
# https://stackoverflow.com/questions/31344892/using-numpys-readtxt-to-read-hex-numbers
array = np.loadtxt('0ACDbR5M3ZhBJajygTuf.bytes.txt', np.uint8, converters={x: conv for x in range(17)}, usecols=list(range(1, 17)))

width = 320  # Select constant width (just an example)
# Or: width = int((array.size / 3)**0.5)

# Assume we want the width to be 320, the number of elements before reshape must be a multiple of 320*3
array = array.ravel()  # Make the arre 1D
remainder = array.size % (width*3)
if remainder > 0:
    array = array[0:-remainder]  # May remove up to 320*3-1 elements from the end of array (make the length a multiple of 320*3)

#https://numpy.org/doc/stable/reference/generated/numpy.reshape.html
# Make the width 320, the number of channels 3, and the height is computed automatically.
rgb_array = array.reshape((-1, width, 3))

im = Image.fromarray(rgb_array, mode='RGB')
im.save('im.jpg')

另一个选项是制作3个彩色平面(R平面、G平面、B平面),并且使用np.transpose

rgb_array = array.reshape((3, width, -1))
rgb_array = np.transpose(rgb_array, (2, 1, 0))

注:
我认为使用JPEG格式不是一个好主意,因为JPEG应用有损压缩。
我建议使用PNG文件格式(PNG是无损的)。

相关问题