実現したいこと
YUVで読み込んだ画像をBMPに変換して保存したい
問題点
図Aはインプット画像でYUV形式の画像です.図Bはアウトプット画像ですが,本来黒であるべき部分が白くなってしまいます.
図A インプット
やったこと
read_YUVにインプット画像を入れて読み込む.出力は[フレーム数,高さ,幅,3]の4次元のnumpy.array.
次にyuv_to_rgb()で8bitフルスケールへ変換.
これを画像に保存したいわけですが,そのままImage.fromarray()を使って保存しようとしたらTypeErrorが出てしまったので
ここを参考に作りました.
Python
1import os, cv2, glob 2import numpy as np 3from PIL import Image 4 5def read_YUV(filePath, height, width, frameNumber=0, count=1, colorFormat=444, depth=8, Y_only=False): 6 ''' 7 処理内容 8 画像を読み込み,[フレーム数, 高さ, 幅, 3 or 1]の4次元配列に格納する. 9 カラーフォーマット420の場合,NearestNeighbor法に基づいてuy成分を2倍に拡大する. 10 引数 11 filePath:画像のパス 12 height:高さ 13 width:幅 14 frameNumber:読み込み開始フレーム番号(デフォルト0) 15 count:読み込むフレーム数(デフォルト1) 16 colorFormat:カラーフォーマット(デフォルト420) 17 depth:ファイルのビット深度 18 Y_only:Trueなら輝度だけ読み込む(デフォルトFalse) 19 戻り値 20 [フレーム数, 高さ, 幅, 3 or 1]の配列(dtype=np.uint8) 21 ''' 22 23 if colorFormat == 420: 24 colorStride = 1.5 25 else: 26 colorStride = 3 27 if depth == 8: 28 depthStride = 1 29 dtype = np.uint8 30 elif depth > 8: 31 depthStride = 2 32 dtype = np.uint16 33 34 with open(filePath,'rb') as fp: 35 #目的のフレームまでシーク 36 fp.seek(int(height*width*frameNumber*depthStride*colorStride),0) 37 38 listImgY = [] 39 listImgUV = [] 40 41 for c in range(count): 42 bary = np.fromfile(fp,dtype=dtype,count=height*width) 43 imgY = np.reshape(bary,(1,height, width,1)) 44 listImgY.append(imgY) 45 46 if Y_only is False: 47 if colorFormat == 420: 48 bary = np.fromfile(fp,dtype=dtype,count=int((height/2)*(width/2)*2)) 49 imgUV = np.reshape(bary,(2,int(height/2),int(width/2),1)) 50 imgUV = np.transpose(imgUV,(3,1,2,0)) 51 imgUV = imgUV.repeat(2, axis=1).repeat(2, axis=2) 52 listImgUV.append(imgUV) 53 elif colorFormat == 444: 54 bary = np.fromfile(fp,dtype=dtype,count=height*width*2) 55 imgUV = np.reshape(bary,(2,height,width,1)) 56 imgUV = np.transpose(imgUV,(3,1,2,0)) 57 listImgUV.append(imgUV) 58 else: 59 fp.seek(int(height*width*depthStride*(colorStride-1)),1) 60 61 imagesY = np.concatenate(listImgY,axis=0) 62 if Y_only is False: 63 imagesUV = np.concatenate(listImgUV,axis=0) 64 images = np.concatenate([imagesY,imagesUV],axis=3) 65 return images 66 else: 67 return imagesY 68 69def yuv_to_rgb(img): 70 ''' 71 処理内容 72 ITU-R BT.601 規定YCbCrから8bitフルスケールRGBへの変換を行う 73 参考サイト:https://vision.kuee.kyoto-u.ac.jp/~hiroaki/firewire/yuv.html 74 引数 75 img:画像データ[高さ, 幅, 3] 76 戻り値 77 [高さ, 幅, 3]のrgb配列(dtype=np.float32) 78 79 ''' 80 height = img.shape[1] 81 width = img.shape[2] 82 83 rgb = np.zeros((1,height,width,3),dtype=np.float32) 84 img = img.astype(np.float32) 85 86 rgb[:,:,:,0] = 1.164 * (img[:,:,:,0]-16) + 1.596 * (img[:,:,:,2] - 128) 87 rgb[:,:,:,1] = 1.164 * (img[:,:,:,0]-16) - 0.391 * (img[:,:,:,1] - 128) - 0.813 * (img[:,:,:,2] -128) 88 rgb[:,:,:,2] = 1.164 * (img[:,:,:,0]-16) + 2.018 * (img[:,:,:,1] - 128) 89 rgb = np.floor(rgb) 90 return rgb 91 92if __name__ == '__main__': 93 file = './test.yuv' 94 img =read_YUV(file, height, width).astype('float') //YUV読み込み用関数 95 img_n = yuv_to_rgb(img) //8bitフルスケールRGBへ変換 96 img_nn = img_n[0,:,:,] //3次元にシェイプ 97 98 arrayimage = np.asarray(img_nn) 99 scale = 255.0 / np.max(arrayimage) 100 pilImg = Image.fromarray(np.uint8(arrayimage*scale))
Python
1arrayimage = np.asarray(img_nn) 2scale = 255.0 / np.max(arrayimage) 3pilImg = Image.fromarray(np.uint8(arrayimage*scale))
おそらくmain内のこの部分が間違えていると思うのですがよくわからないのでどなたかご教授願います.
あなたの回答
tips
プレビュー