From fc9eece101d3f2d2c6557655f2611e0222f4c37e Mon Sep 17 00:00:00 2001 From: Cao Sen Miao Date: Wed, 17 Apr 2024 14:37:04 +0800 Subject: [PATCH] change(jpeg): modify open_rgb.py for its now supporting open YUV files --- .../peripherals/jpeg/jpeg_decode/README.md | 2 +- .../jpeg/jpeg_decode/open_raw_picture.py | 189 ++++++++++++++++++ .../peripherals/jpeg/jpeg_decode/open_rgb.py | 91 --------- 3 files changed, 190 insertions(+), 92 deletions(-) create mode 100644 examples/peripherals/jpeg/jpeg_decode/open_raw_picture.py delete mode 100644 examples/peripherals/jpeg/jpeg_decode/open_rgb.py diff --git a/examples/peripherals/jpeg/jpeg_decode/README.md b/examples/peripherals/jpeg/jpeg_decode/README.md index 7947801298..ff99171c3e 100644 --- a/examples/peripherals/jpeg/jpeg_decode/README.md +++ b/examples/peripherals/jpeg/jpeg_decode/README.md @@ -51,7 +51,7 @@ I (13336) jpeg.example: Card unmounted I (13336) main_task: Returned from app_main() ``` -Moreover, we provided a helper script called `open_rgb.py`, which can help you easily see the outputs on your computer. For requirements component you need, you can call `pip install -r requirements.txt` under `examples/peripheral/jpeg/jpeg_decode` folder. +Also, the helper script [open_raw_picture.py](./open_raw_picture.py) simplifies the visualization of the output on your computer. For this to work, go to `examples/peripheral/jpeg/jpeg_decode` and install the requirements by running `pip install -r requirements.txt`. ## Troubleshooting diff --git a/examples/peripherals/jpeg/jpeg_decode/open_raw_picture.py b/examples/peripherals/jpeg/jpeg_decode/open_raw_picture.py new file mode 100644 index 0000000000..e92fe0973d --- /dev/null +++ b/examples/peripherals/jpeg/jpeg_decode/open_raw_picture.py @@ -0,0 +1,189 @@ +# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Unlicense OR CC0-1.0 +import argparse + +import cv2 as cv +import numpy as np +from numpy.typing import NDArray + + +def open_picture(path): # type: (str) -> list[int] + with open(path, 'rb') as f: + data = f.read() + f.close() + new_data = [int(x) for x in data] + return new_data + + +def picture_show_rgb888(data, h, w): # type: (list[int], int, int) -> None + data = np.array(data).reshape(h, w, 3).astype(np.uint8) + cv.imshow('data', data) + cv.waitKey() + + +def picture_show_rgb565(data, h, w): # type: (list[int], int, int) -> None + + new_data = [0] * ((len(data) // 2) * 3) + for i in range(len(data)): + if i % 2 != 0: + new_data[3 * (i - 1) // 2 + 2] = (data[i] & 0xf8) + new_data[3 * (i - 1) // 2 + 1] |= (data[i] & 0x7) << 5 + else: + new_data[3 * i // 2] = (data[i] & 0x1f) << 3 + new_data[3 * i // 2 + 1] |= (data[i] & 0xe0) >> 3 + + new_data = np.array(new_data).reshape(h, w, 3).astype(np.uint8) + cv.imshow('data', new_data) + cv.waitKey() + + +def picture_show_gray(data, h, w): # type: (list[int], int, int) -> None + new_data = np.array(data).reshape(h, w, 1).astype(np.uint8) + cv.imshow('data', new_data) + cv.waitKey() + + +def convert_YUV_to_RGB(Y, U, V): # type: (NDArray, NDArray, NDArray) -> tuple[NDArray, NDArray, NDArray] + B = np.clip(Y + 1.7790 * (U - 128), 0, 255).astype(np.uint8) + G = np.clip(Y - 0.3455 * (U - 128) - 0.7169 * (V - 128), 0, 255).astype(np.uint8) + R = np.clip(Y + 1.4075 * (V - 128), 0, 255).astype(np.uint8) + + return B, G, R + + +def picture_show_yuv420(data, h, w): # type: (list[int], int, int) -> None + new_u = [0] * (h * w) + new_v = [0] * (h * w) + new_y = [0] * (h * w) + + for i in range(int(h * w * 1.5)): + is_even_row = ((i // (w * 1.5)) % 2 == 0) + if is_even_row: + if (i % 3 == 0): + new_u[(i // 3) * 2] = data[i] + new_u[(i // 3) * 2 + 1] = data[i] + else: + if (i % 3 == 0): + new_u[(i // 3) * 2] = new_u[int((i - (w * 1.5)) // 3) * 2] + new_u[(i // 3) * 2 + 1] = new_u[int((i - (w * 1.5)) // 3) * 2 + 1] + + for i in range(int(h * w * 1.5)): + if (i // (w * 1.5)) % 2 != 0 and (i % 3 == 0): + idx = (i // 3) * 2 + new_v[idx] = data[i] + new_v[idx + 1] = data[i] + + for i in range(int(h * w * 1.5)): + if (i // (w * 1.5)) % 2 == 0 and (i % 3 == 0): + idx = (i // 3) * 2 + new_v[idx] = new_v[int((i + (w * 1.5)) // 3) * 2] + new_v[idx + 1] = new_v[int((i + (w * 1.5)) // 3) * 2 + 1] + + new_y = [data[i] for i in range(int(h * w * 1.5)) if i % 3 != 0] + + Y = np.array(new_y) + U = np.array(new_u) + V = np.array(new_v) + + B, G, R = convert_YUV_to_RGB(Y, U, V) + # Merge channels + new_data = np.stack((B, G, R), axis=-1) + new_data = np.array(new_data).reshape(h, w, 3).astype(np.uint8) + + # Display the image + cv.imshow('data', new_data) + cv.waitKey() + + +def picture_show_yuv422(data, h, w): # type: (list[int], int, int) -> None + # Reshape the input data to a 2D array + data_array = np.array(data).reshape(h, w * 2) + + # Separate Y, U, and V channels + Y = data_array[:, 1::2] + U = data_array[:, 0::4].repeat(2, axis=1) + V = data_array[:, 2::4].repeat(2, axis=1) + + # Convert YUV to RGB + B, G, R = convert_YUV_to_RGB(Y, U, V) + + # Merge channels + new_data = np.stack((B, G, R), axis=-1) + + # Display the image + cv.imshow('data', new_data) + cv.waitKey() + + +def picture_show_yuv444(data, h, w): # type: (list[int], int, int) -> None + # Reshape the input data to a 2D array + data_array = np.array(data).reshape(h, w * 3) + + # Separate Y, U, and V channels + Y = data_array[:, 2::3] + U = data_array[:, 1::3] + V = data_array[:, 0::3] + + # Convert YUV to RGB + B, G, R = convert_YUV_to_RGB(Y, U, V) + + # Merge channels + new_data = np.stack((B, G, R), axis=-1) + + # Display the image + cv.imshow('data', new_data) + cv.waitKey() + + +def main(): # type: () -> None + parser = argparse.ArgumentParser(description='which mode need to show') + + parser.add_argument( + '--pic_path', + type=str, + help='What is the path of your picture', + required=True) + + parser.add_argument( + '--pic_type', + type=str, + help='What type you want to show', + required=True, + choices=['rgb565', 'rgb888', 'gray', 'yuv422', 'yuv420', 'yuv444']) + + parser.add_argument( + '--height', + type=int, + help='the picture height', + default=480) + + parser.add_argument( + '--width', + type=int, + help='the picture width', + default=640) + + args = parser.parse_args() + + height = args.height + width = args.width + + data = open_picture('/media/simon/USB STICK/420.YUV') + if (args.pic_type == 'rgb565'): + picture_show_rgb565(data, height, width) + elif (args.pic_type == 'rgb888'): + picture_show_rgb888(data, height, width) + elif (args.pic_type == 'gray'): + picture_show_gray(data, height, width) + elif (args.pic_type == 'yuv420'): + picture_show_yuv420(data, height, width) + elif (args.pic_type == 'yuv422'): + picture_show_yuv422(data, height, width) + elif (args.pic_type == 'yuv444'): + picture_show_yuv444(data, height, width) + else: + print('This type is not supported in this script!') + + +if __name__ == '__main__': + main() diff --git a/examples/peripherals/jpeg/jpeg_decode/open_rgb.py b/examples/peripherals/jpeg/jpeg_decode/open_rgb.py deleted file mode 100644 index c78809627f..0000000000 --- a/examples/peripherals/jpeg/jpeg_decode/open_rgb.py +++ /dev/null @@ -1,91 +0,0 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD -# SPDX-License-Identifier: Unlicense OR CC0-1.0 -import argparse - -import cv2 as cv -import numpy as np - - -def open_picture(path): # type: (str) -> list[int] - with open(path, 'rb') as f: - data = f.read() - f.close() - new_data = [int(x) for x in data] - return new_data - - -def picture_show_rgb888(data, h, w): # type: (list[int], int, int) -> None - data = np.array(data).reshape(h, w, 3).astype(np.uint8) - cv.imshow('data', data) - cv.waitKey() - - -def picture_show_rgb565(data, h, w): # type: (list[int], int, int) -> None - - new_data = [0] * ((len(data) // 2) * 3) - for i in range(len(data)): - if i % 2 != 0: - new_data[3 * (i - 1) // 2 + 2] = (data[i] & 0xf8) - new_data[3 * (i - 1) // 2 + 1] |= (data[i] & 0x7) << 5 - else: - new_data[3 * i // 2] = (data[i] & 0x1f) << 3 - new_data[3 * i // 2 + 1] |= (data[i] & 0xe0) >> 3 - - new_data = np.array(new_data).reshape(h, w, 3).astype(np.uint8) - cv.imshow('data', new_data) - cv.waitKey() - - -def picture_show_gray(data, h, w): # type: (list[int], int, int) -> None - new_data = np.array(data).reshape(h, w, 1).astype(np.uint8) - cv.imshow('data', new_data) - cv.waitKey() - - -def main(): # type: () -> None - parser = argparse.ArgumentParser(description='which mode need to show') - - parser.add_argument( - '--pic_path', - type=str, - help='What is the path of your picture', - required=True) - - parser.add_argument( - '--pic_type', - type=str, - help='What type you want to show', - required=True, - choices=['rgb565', 'rgb888', 'gray']) - - parser.add_argument( - '--hight', - type=int, - help='the picture hight', - default=480) - - parser.add_argument( - '--width', - type=int, - help='the picture width', - default=640) - - args = parser.parse_args() - - hight = args.hight - width = args.width - - data = open_picture(args.pic_path) - - if (args.pic_type == 'rgb565'): - picture_show_rgb565(data, hight, width) - elif (args.pic_type == 'rgb888'): - picture_show_rgb888(data, hight, width) - elif (args.pic_type == 'gray'): - picture_show_gray(data, hight, width) - else: - print('This type is not supported in this script!') - - -if __name__ == '__main__': - main()