使用CNN预测HEVC的CU分割 (2) -- 数据集的划分,随机抽取帧,优化数据集结构加快读取

我自己生成的数据集在GitHub,包含了训练、测试、验证集:

GitHub - wolverinn/HEVC-CU-depths-dataset: A dataset that contains the Coding Unit image files and their corresponding depths for HEVC intra-prediction.

关于数据集的准备部分,还有一些更加细节的工作需要完成。首先就是训练集,验证集和测试集的划分,在数据集中使用的所有YUV序列如下:

type Train Validation Test
4K Bund-Nightscape_3840x2160_30 Campfire-Party_3840x2160_30 Construction-Field_3840x2160_30
Fountains_3840x2160_30 Library_3840x2160_30 Marathon_3840x2160_30
Residential-Building_3840x2160_30 Runners_3840x2160_30 Rush-Hour_3840x2160_30
Scarf_3840x2160_30
Tall-Buildings_3840x2160_30
Traffic-and-Building_3840x2160_30
Traffic-Flow_3840x2160_30
Tree-Shade_3840x2160_30
Wood_3840x2160_30
2K NebutaFestival_2560x1600_60 PeopleOnStreet_2560x1600_30 Traffic_2560x1600_30
SteamLocomotiveTrain_2560x1600_60
1080p BasketballDrive_1920x1080_50 BQTerrace_1920x1080_60 Cactus_1920x1080_50
Kimono1_1920x1080_24
Tennis_1920x1080_24
ParkScene_1920x1080_24
720p FourPeople_1280x720_60 SlideShow_1280x720_20 KristenAndSara_1280x720_60
SlideEditing_1280x720_30
Johnny_1280x720_60
480p BasketballDrill_832x480_50 Flowervase_832x480_30 BQMall_832x480_60
Keiba_832x480_30 Mobisode2_832x480_30 PartyScene_832x480_50
RaceHorses_832x480_30
288 waterfall_352x288_20 akiyo_352x288_20 bridge-close_352x288_20
bridge-far_352x288_20 coastguard_352x288_20 container_352x288_20
flower_352x288_20 foreman_352x288_20 hall_352x288_20
highway_352x288_20 mobile_352x288_20 mother-daughter_352x288_20
news_352x288_20
paris_352x288_20
silent_352x288_20
tempete_352x288_20
240 BasketballPass_416x240_50 BlowingBubbles_416x240_50 BQSquare_416x240_60

由于存储空间的限制以及相邻帧之间的高度相似,所以在训练的时候并不会使用从一个YUV文件中抽取出的所有帧,而是会随机抽取一些帧,参考下面的公式来选取帧:

n = (25 + f/40) / 40

每个YUV的第2帧和第27帧都被抽取,之后的第n个帧就按照上面的公式抽取,f代表YUV文件的总帧数。代码:

def crop_image_to_ctu(video_number):
    frames = len(os.listdir("{}\\temp-frames".format(WORKSPACE_PATH))) # 当前视频一共有多少帧
    random_frames = [2,27]
    n = int((25+frames/40)//4)
    for i in range(frames//n):
        f_index = 27 + n*(i+1)
        if f_index > frames:
            break
        else:
            random_frames.append(f_index) # 随机抽取帧,有一个公式得出抽取的帧的编号
    for image_file in os.listdir("{}\\temp-frames".format(WORKSPACE_PATH)):
        frame_number = int(image_file.split('_')[2])-1 # ffmpeg生成帧编号是从1开始,这里减1将编号变成从0开始和ctu分割信息对应
        if frame_number in random_frames:
            img = Image.open(os.path.join("{}\\temp-frames".format(WORKSPACE_PATH),image_file))
            img_width, img_height = img.size
            ctu_number_per_img = math.ceil(img_width / 64) * math.ceil(img_height / 64)
            for ctu_number in range(ctu_number_per_img):
                img_row = ctu_number // math.ceil(img_width / 64)
                img_colonm = ctu_number % math.ceil(img_height / 64)
                start_pixel_x = img_colonm * 64
                start_pixel_y = img_row * 64
                cropped_img = img.crop((start_pixel_x, start_pixel_y, start_pixel_x + 64, start_pixel_y + 64)) # 依次对抽取到的帧进行裁剪
                cropped_img.save("{}\\v_{}_{}_{}_.jpg".format(IMG_PATH,video_number,str(frame_number),str(ctu_number)))
            img.close()
            dump_ctu_file(video_number, str(frame_number)) # 将当前帧的所有ctu分割信息保存到新的文件,只保存抽取的帧的信息
        os.remove(os.path.join("{}\\temp-frames".format(WORKSPACE_PATH),image_file)) # 裁剪过后的帧就删掉
    print("Total frames extracted from video_{} : {}".format(video_number,len(random_frames)))

在生成数据集的过程中,我发现对于CTU的分割信息,如果将YUV的所有帧的分割信息保存到txt文件,这样一个YUV就会产生几十兆甚至1080P的YUV会产生一百多兆的文本文件,这样会导致训练的时候每加载一个CTU分割信息都会花费一定的时间,影响训练的效率。所以首先想到的是不用保存所有的分割信息,只需要保存之前抽取出的帧的CTU划分信息就可以了,这样可以大大减少存储空间。其次,还可以对保存的数据结构进行优化,如果保存在文本文件中,每次的读取方式就只能从第一行开始遍历,直到找到对应的帧的CTU,效率也很低。所以我将需要保存的CTU划分信息保存到了Python的字典(dict)中,结构如下:

video_0 = {
    "frame_2":{
        "ctu_0":[...] # 16x16的划分信息
        "ctu_1":[...]
        .
        .
        .
        "ctu_103":[...]
    }
    "frame_27":{
        ...
    }
}

这样可以快速根据图片是第几帧,第几个CTU找到对应的划分信息。将这个字典使用Python自带的持久化库pickle保存到v_0.pkl,在使用的时候可以方便地进行读取。代码如下:

def dump_ctu_file(video_number,frame_number):
    # 将抽取到的帧的所有ctu分割信息保存到pickle:{"frame_number_1":{"ctu_number_1":[...];"ctu_number_2":[...]};"frame_number_2":...}
    frame_detected = 0
    ctu_number = "0"
    temp_ctu = []
    f_pkl = open("v_{}.pkl".format(video_number), 'rb')
    video_dict = pickle.load(f_pkl)
    f_pkl.close()
    video_dict[frame_number] = {}
    with open(CtuInfo_FILENAME,'r') as f:
        for i,line in enumerate(f):
            if frame_detected == 0:
                if "frame" in line:
                    current_frame = line.split(':')[1]
                    if int(frame_number) == int(current_frame):
                        frame_detected = 1
            elif "frame" in line:
                break
            elif "ctu" in line:
                temp_ctu = []
                ctu_number = int(line.split(':')[1])
                video_dict[frame_number][str(ctu_number)] = []
            else:
                line_depths = line.split(' ')
                for index in range(16):
                    temp_ctu.append(int(line_depths[index]))
                    video_dict[frame_number][str(ctu_number)] = temp_ctu
    f_pkl = open("v_{}.pkl".format(video_number), 'wb')
    pickle.dump(video_dict, f_pkl)
    f_pkl.close()

数据预处理是神经网络训练中的一个很重要也很花费时间的环节,必须考虑到神经网络所需要的格式化的输入,如何将图片与标签对应,以及读取所花费的时间的优化。根据这些去对原始数据使用一定的规则进行处理。只有数据预处理部分做好了,才能在训练部分专注于神经网络而不是一些琐碎的数据处理规则。

我自己生成的数据集GitHub地址:

HEVC-CU-depths-dataset

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,907评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,987评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,298评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,586评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,633评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,488评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,275评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,176评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,619评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,819评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,932评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,655评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,265评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,871评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,994评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,095评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,884评论 2 354

推荐阅读更多精彩内容