其他分享
首页 > 其他分享> > 电子科技大学-图像与视频处理作业

电子科技大学-图像与视频处理作业

作者:互联网

题目给定图像“foreman.qcif”,利用C/python语言进行以下编程操作

1.读取原始视频序列(2帧),其中第1帧为I帧,第2帧为P帧(本次作业第2帧可简单做与第1帧的整体图像帧差值);(20分)

2.进行8x8分块的DCT变换;(15分)

3.设定量化步长Qstep=22进行量化;(10分)

4.完成相应的反量化和反DCT变换;(25分)

5.将重组数据写入文件“re_foreman.qcif”(2帧);(20分)6.计算“foreman.qcif”和“re_foreman.qcif”的PSNR。(10分)

python代码:

#图像与视频处理作业
# 给定图像“foreman.qcif”,利用C语言进行以下编程操作
# 1.读取原始视频序列(2帧),其中第1帧为I帧,第2帧为P帧(本次作业第2帧可简单做与第1帧的整体图像帧差值);(20分)
# 2.进行8x8分块的DCT变换;(15分)
# 3.设定量化步长Qstep=22进行量化;(10分)
# 4.完成相应的反量化和反DCT变换;(25分)
# 5.将重组数据写入文件“re_foreman.qcif”(2帧);(20分)6.计算“foreman.qcif”和“re_foreman.qcif”的PSNR。(10分)
# -*- coding: utf-8 -*-
import cv2
import numpy as np
import math
PI = 33.14159265358979323
def getFrameInformation(filename,frameNum):
    """
    :param frameNum: 读取哪一帧
    :return: Yt,Ut,Vt: yuv视频三个数据段的数据
    """

    # juv文件路径
    filename = "foreman_qcif.yuv"
    # 视频的尺寸
    height = 144
    width = 176
    # 读取视频数据
    fp = open(filename, 'rb')

    # 获取U,V的高度和宽度
    h_h = height // 2
    h_w = width // 2
    # 定义存储Y,U,V 的矩阵
    Yt = np.zeros(shape=(height, width), dtype='double', order='C')
    Ut = np.zeros(shape=(h_h, h_w), dtype='double', order='C')
    Vt = np.zeros(shape=(h_h, h_w), dtype='double', order='C')
    # for循环获取指定帧的数据
    for i in range(frameNum):
        Yt = np.zeros(shape=(height, width), dtype='double', order='C')
        Ut = np.zeros(shape=(h_h, h_w), dtype='double', order='C')
        Vt = np.zeros(shape=(h_h, h_w), dtype='double', order='C')
        # 获取Y字段的数据
        for m in range(height):
            for n in range(width):
                Yt[m, n] = ord(fp.read(1))
        # 获取U字段的数据
        for m in range(h_h):
            for n in range(h_w):
                Ut[m, n] = ord(fp.read(1))
        # 获取V字段的数据
        for m in range(h_h):
            for n in range(h_w):
                Vt[m, n] = ord(fp.read(1))
    return Yt, Ut, Vt


def compare_predition(frameNum1, frameNum2):
    """
    :param frameNum1: 选择帧数1
    :param frameNum2: 选择帧数2
    :return: Yt2-Yt1,Ut2-Ut1,Vt2-Vt1:两帧三个字段的差值
    """

    # 获取第frameNum1帧的图片的数据
    (Yt1, Ut1, Vt1) = getFrameInformation("foreman_qcif.yuv",1)
    # 获取第frameNum2帧的图片的数据
    (Yt2, Ut2, Vt2) = getFrameInformation("foreman_qcif.yuv",2)
    # 返回三个字段的差值
    return (Yt2 - Yt1, Ut2 - Ut1, Vt2 - Vt1)


def dct(Yt, Ut, Vt):
    """
    :param Yt: 做DCT变换的Y字段
    :param Ut: 做DCT变换的U字段
    :param Vt: 做DCT变换的V字段
    :return:
    """
    # 定义
    Yt_dct = np.zeros(shape=(144, 176), dtype='double', order='C')
    Ut_dct = np.zeros(shape=(72, 88), dtype='double', order='C')
    Vt_dct = np.zeros(shape=(72, 88), dtype='double', order='C')

    # 计算变换矩阵A
    a_array = np.zeros(shape=(8, 8), dtype='double', order='C')
    for i in range(8):
        for j in range(8):
            if i == 0:
                a_array[i][j] = 1 / 8 ** 2
            else:
                a_array[i][j] = 0.5 * math.cos(i * (j + 0.5) * PI / 8)
    # 通过变换矩阵A 得到 其转置矩阵
    at_array = np.zeros(shape=(8, 8), dtype='double', order='C')
    for i in range(8):
        for j in range(8):
            at_array[i][j] = a_array[j][i]
    # 计算Y的DCT变换
    for i in range(18 * 22):
        dct_8_8 = np.zeros(shape=(8, 8), dtype='double', order='C')
        for n in range((i // 22) * 8, (i // 22) * 8 + 8):
            for m in range((i % 22) * 8, (i % 22) * 8 + 8):
                dct_8_8[n % 8][m % 8] = Yt[n][m]
        dct_8_8 = cv2.dct(dct_8_8)
        for n in range((i // 22) * 8, (i // 22) * 8 + 8):
            for m in range((i % 22) * 8, (i % 22) * 8 + 8):
                Yt_dct[n][m] = dct_8_8[n % 8][m % 8]
    # 计算U的DCT变换
    for i in range(9 * 11):
        dct_8_8 = np.zeros(shape=(8, 8), dtype='double', order='C')
        for n in range((i // 11) * 8, (i // 11) * 8 + 8):
            for m in range((i % 11) * 8, (i % 11) * 8 + 8):
                dct_8_8[n % 8][m % 8] = Ut[n][m]
        dct_8_8 = cv2.dct(dct_8_8)
        for n in range((i // 11) * 8, (i // 11) * 8 + 8):
            for m in range((i % 11) * 8, (i % 11) * 8 + 8):
                Ut_dct[n][m] = dct_8_8[n % 8][m % 8]
    # 计算V的DCT变换
    for i in range(9 * 11):
        dct_8_8 = np.zeros(shape=(8, 8), dtype='double', order='C')
        for n in range((i // 11) * 8, (i // 11) * 8 + 8):
            for m in range((i % 11) * 8, (i % 11) * 8 + 8):
                dct_8_8[n % 8][m % 8] = Vt[n][m]
        dct_8_8 = cv2.dct(dct_8_8)
        for n in range((i // 11) * 8, (i // 11) * 8 + 8):
            for m in range((i % 11) * 8, (i % 11) * 8 + 8):
                Vt_dct[n][m] = dct_8_8[n % 8][m % 8]
    # 返回DCT变换的结果
    return Yt_dct, Ut_dct, Vt_dct


def idct(Yt_dct, Ut_dct, Vt_dct):
    Yt_dct = np.float32(Yt_dct)  # 将数值精度调整为32位浮点型
    Ut_dct = np.float32(Ut_dct)  # 将数值精度调整为32位浮点型
    Vt_dct = np.float32(Vt_dct)  # 将数值精度调整为32位浮点型

    Yt_idct = np.zeros(shape=(144, 176), dtype='double', order='C')
    Ut_idct = np.zeros(shape=(72, 88), dtype='double', order='C')
    Vt_idct = np.zeros(shape=(72, 88), dtype='double', order='C')

    # 计算变换矩阵A
    a_array = np.zeros(shape=(8, 8), dtype='double', order='C')
    for i in range(8):
        for j in range(8):
            if i == 0:
                a_array[i][j] = 1 / 8 ** 2
            else:
                a_array[i][j] = 0.5 * math.cos(i * (j + 0.5) * PI / 8)
    # 通过变换矩阵A 得到 其转置矩阵
    at_array = np.zeros(shape=(8, 8), dtype='double', order='C')
    for i in range(8):
        for j in range(8):
            at_array[i][j] = a_array[j][i]
    # 计算Y的DCT变换
    for i in range(18 * 22):
        idct_8_8 = np.zeros(shape=(8, 8), dtype='double', order='C')
        for n in range((i // 22) * 8, (i // 22) * 8 + 8):
            for m in range((i % 22) * 8, (i % 22) * 8 + 8):
                idct_8_8[n % 8][m % 8] = Yt_dct[n][m]
        idct_8_8 = cv2.idct(idct_8_8)
        for n in range((i // 22) * 8, (i // 22) * 8 + 8):
            for m in range((i % 22) * 8, (i % 22) * 8 + 8):
                Yt_idct[n][m] = idct_8_8[n % 8][m % 8]
    # 计算U的DCT变换
    for i in range(9 * 11):
        idct_8_8 = np.zeros(shape=(8, 8), dtype='double', order='C')
        for n in range((i // 11) * 8, (i // 11) * 8 + 8):
            for m in range((i % 11) * 8, (i % 11) * 8 + 8):
                idct_8_8[n % 8][m % 8] = Ut_dct[n][m]
        idct_8_8 = cv2.idct(idct_8_8)
        for n in range((i // 11) * 8, (i // 11) * 8 + 8):
            for m in range((i % 11) * 8, (i % 11) * 8 + 8):
                Ut_idct[n][m] = idct_8_8[n % 8][m % 8]
    # 计算V的DCT变换
    for i in range(9 * 11):
        idct_8_8 = np.zeros(shape=(8, 8), dtype='double', order='C')
        for n in range((i // 11) * 8, (i // 11) * 8 + 8):
            for m in range((i % 11) * 8, (i % 11) * 8 + 8):
                idct_8_8[n % 8][m % 8] = Vt_dct[n][m]
        idct_8_8 = cv2.idct(idct_8_8)
        for n in range((i // 11) * 8, (i // 11) * 8 + 8):
            for m in range((i % 11) * 8, (i % 11) * 8 + 8):
                Vt_idct[n][m] = idct_8_8[n % 8][m % 8]
    # 返回DCT变换的结果
    return Yt_idct, Ut_idct, Vt_idct


def qstep(Yt, Ut, Vt):
    Yt = np.uint8(Yt)
    Ut = np.uint8(Ut)
    Vt = np.uint8(Vt)
    Yt_q = np.zeros(shape=(144, 176), dtype='uint8', order='C')
    Ut_q = np.zeros(shape=(72, 88), dtype='uint8', order='C')
    Vt_q = np.zeros(shape=(72, 88), dtype='uint8', order='C')

    for i in range(144):
        for j in range(176):
            Yt_q[i][j] = Yt[i][j] // 22
    for i in range(72):
        for j in range(88):
            Ut_q[i][j] = Ut[i][j] // 22
    for i in range(72):
        for j in range(88):
            Vt_q[i][j] = Vt[i][j] // 22

    return Yt_q, Ut_q, Vt_q


def iqstep(Yt_q, Ut_q, Vt_q):
    Yt_q = np.uint8(Yt_q)
    Ut_q = np.uint8(Ut_q)
    Vt_q = np.uint8(Vt_q)

    Yt_iq = np.zeros(shape=(144, 176), dtype='uint8', order='C')
    Ut_iq = np.zeros(shape=(72, 88), dtype='uint8', order='C')
    Vt_iq = np.zeros(shape=(72, 88), dtype='uint8', order='C')

    for i in range(144):
        for j in range(176):
            Yt_iq[i][j] = Yt_q[i][j] * 22
    for i in range(72):
        for j in range(88):
            Ut_iq[i][j] = Ut_q[i][j] * 22
    for i in range(72):
        for j in range(88):
            Vt_iq[i][j] = Vt_q[i][j] * 22

    return Yt_iq, Ut_iq, Vt_iq


def writeqcif(filename, Yt, Ut, Vt):
    Yt = np.uint8(Yt)
    Ut = np.uint8(Ut)
    Vt = np.uint8(Vt)
    ff = open(filename, "wb+")
    for i in range(144):
        for j in range(176):
            ff.write(Yt[i][j])
    for i in range(72):
        for j in range(88):
            ff.write(Ut[i][j])
    for i in range(72):
        for j in range(88):
            ff.write(Vt[i][j])
    return None

# 图像信噪比是用于评估图像超分结果的指标
def psnr(Yt1, Ut1, Vt1, Yt2, Ut2, Vt2):
    ch_num = 0
    #遍历图像
    for i in range(144):
        for j in range(176):
            ch_num = ch_num + (math.fabs(Yt1[i][j]/255. - Yt2[i][j]/255.))**2
    for i in range(72):
        for j in range(88):
            ch_num = ch_num + (math.fabs(Ut1[i][j]/255. - Ut2[i][j]/255.))**2
    for i in range(72):
        for j in range(88):
            ch_num = ch_num + (math.fabs(Vt1[i][j]/255. - Vt2[i][j]/255.))**2
    ch_num = ch_num/(144*3/2*176)
    if ch_num < 1.0e-10:
        return 100
    PIXEL_MAX = 1
    return 20 * math.log10(PIXEL_MAX / math.sqrt(ch_num))


if __name__ == '__main__':
    # 从视频中获取第一帧和第二帧数据
    (Yt1, Ut1, Vt1) = getFrameInformation("foreman_qcif.yuv",1)
    (Yt2, Ut2, Vt2) = getFrameInformation("foreman_qcif.yuv",2)
    # 图像化第一帧
    writeqcif("foreman1.qcif", Yt1, Ut1, Vt1)
    # 图像化第二帧
    writeqcif("foreman2.qcif", Yt2, Ut2, Vt2)
    #1.predition
    (Yt_predition, Ut_predition, Vt_prediton) = compare_predition(1, 2)
    print(Yt_predition,Ut_predition,Vt_prediton)
    #2.进行DCT变换
    (Yt_dct, Ut_dct, Vt_dct) = dct(Yt1, Ut1, Vt1)
    #3.进行量化处理
    (Yt_q, Ut_q, Vt_q) = qstep(Yt_dct, Ut_dct, Vt_dct)
    #4.进行反量化
    (Yt_iq, Ut_iq, Vt_iq) = iqstep(Yt_q, Ut_q, Vt_q)
    Yt_iq = np.float32(Yt_iq)  # 将数值精度调整为32位浮点型
    Ut_iq = np.float32(Ut_iq)  # 将数值精度调整为32位浮点型
    Vt_iq = np.float32(Vt_iq)  # 将数值精度调整为32位浮点型
    #5.进行IDCT变换
    Yt_idct, Ut_idct, Vt_idct = idct(Yt_iq, Ut_iq, Vt_iq)
    # 将变换后的数据写入新的文件中
    writeqcif("re_foreman1.qcif", Yt_idct, Ut_idct, Vt_idct)


    # 对第二帧数据进行相同处理
    # 进行DCT变换
    (Yt_dct2, Ut_dct2, Vt_dct2) = dct(Yt2, Ut2, Vt2)
    # 进行量化处理
    (Yt_q2, Ut_q2, Vt_q2) = qstep(Yt_dct2, Ut_dct2, Vt_dct2)
    # 进行反量化
    (Yt_iq2, Ut_iq2, Vt_iq2) = iqstep(Yt_q2, Ut_q2, Vt_q2)
    # 进行IDCT变换
    Yt_idct2, Ut_idct2, Vt_idct2 = idct(Yt_iq2, Ut_iq2, Vt_iq2)
    # 将变换后的数据写入新的文件中
    writeqcif("re_foreman2.qcif", Yt_idct2, Ut_idct2, Vt_idct2)

    #输出
    print("第一帧原始图像与进行变换后图像的qsnr值为:")
    print(psnr(Yt1, Ut1, Vt1,Yt_idct, Ut_idct, Vt_idct))

    print("第二帧原始图像与进行变换后图像的qsnr值为:")
    print(psnr(Yt2, Ut2, Vt2, Yt_idct2, Ut_idct2, Vt_idct2))

结果展示:

1.读取原始视频序列(2帧),其中第1帧为I帧,第2帧为P帧(本次作业第2帧可简单做与第1帧的整体图像帧差值);(20分)

第一帧图像及3通道信息:

图像:

 

y通道:

u通道

 

v通道

 

第一帧与第二帧的差值

Y_predition

 

U_predition

 

V_predition

 

2.进行8x8分块的DCT变换;(15分)

Y_DCT

 

U_DCT

 

V_DCT

 

3.设定量化步长Qstep=22进行量化;(10分) ------合并写

4.完成相应的反量化和反DCT变换;(25分) -------合并写

Y_IDCT

 

U_IDCT

 

V_IDCT

 

5.将重组数据写入文件“re_foreman.qcif”(2帧);(20分)6.计算“foreman.qcif”和“re_foreman.qcif”的PSNR。(10分)

只进行dct和idct重组出的两幅qcif图

 

 

进行进行8x8分块的DCT变换,设定量化步长Qstep=22进行量化;完成相应的反量化和反DCT变换重组出的两幅qcif图

 

 

计算出的PSNR

 

第一帧原始图像与进行变换后图像的qsnr值为:

2.541566509325704

第二帧原始图像与进行变换后图像的qsnr值为:

2.545820360785359

标签:视频,Ut,电子科技,range,Vt,图像,np,dct,Yt
来源: https://blog.csdn.net/a2274001782/article/details/117132295