Skip to content

lib: pixel: distort: add distortion aka defisheye aka dewarp #88840

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions MAINTAINERS.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3203,6 +3203,21 @@ PHYTEC Platforms:
labels:
- "platform: PHYTEC"

Pixel library:
status: maintained
maintainers:
- josuah
files:
- include/zephyr/pixel/
- lib/pixel/
- tests/lib/pixel/
- samples/lib/pixel/
labels:
- "area: Pixel Library"
tests:
- libraries.pixel
description: Library for pixel manipulation and image processing

PMCI:
status: maintained
maintainers:
Expand Down
6 changes: 6 additions & 0 deletions cmake/linker_script/common/common-ram.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,12 @@ if(CONFIG_PCIE)
zephyr_iterable_section(NAME pcie_dev GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN ${CONFIG_LINKER_ITERABLE_SUBALIGN})
endif()

if(CONFIG_PIXEL)
zephyr_iterable_section(NAME pixel_convert GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN ${CONFIG_LINKER_ITERABLE_SUBALIGN})
zephyr_iterable_section(NAME pixel_resize GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN ${CONFIG_LINKER_ITERABLE_SUBALIGN})
zephyr_iterable_section(NAME pixel_kernel GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN ${CONFIG_LINKER_ITERABLE_SUBALIGN})
endif()

if(CONFIG_USB_DEVICE_STACK OR CONFIG_USB_DEVICE_STACK_NEXT)
zephyr_iterable_section(NAME usbd_context GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN ${CONFIG_LINKER_ITERABLE_SUBALIGN})
zephyr_iterable_section(NAME usbd_class_fs GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN ${CONFIG_LINKER_ITERABLE_SUBALIGN})
Expand Down
17 changes: 17 additions & 0 deletions include/zephyr/drivers/video.h
Original file line number Diff line number Diff line change
Expand Up @@ -1211,6 +1211,13 @@ void video_closest_frmival(const struct device *dev, enum video_endpoint_id ep,
* @{
*/

/**
* @code{.unparsed}
* | RrrGggBb | ...
* @endcode
*/
#define VIDEO_PIX_FMT_RGB332 VIDEO_FOURCC('R', 'G', 'B', '1')

/**
* 5 red bits [15:11], 6 green bits [10:5], 5 blue bits [4:0].
* This 16-bit integer is then packed in big endian format over two bytes:
Expand Down Expand Up @@ -1333,6 +1340,13 @@ void video_closest_frmival(const struct device *dev, enum video_endpoint_id ep,
*/
#define VIDEO_PIX_FMT_UYVY VIDEO_FOURCC('U', 'Y', 'V', 'Y')

/**
* @code{.unparsed}
* | Yyyyyyyy Uuuuuuuu Vvvvvvvv | ...
* @endcode
*/
#define VIDEO_PIX_FMT_YUV24 VIDEO_FOURCC('Y', 'U', 'V', '3')

/**
* The first byte is empty (X) for each pixel.
*
Expand Down Expand Up @@ -1376,6 +1390,7 @@ static inline unsigned int video_bits_per_pixel(uint32_t pixfmt)
case VIDEO_PIX_FMT_GRBG8:
case VIDEO_PIX_FMT_RGGB8:
case VIDEO_PIX_FMT_GREY:
case VIDEO_PIX_FMT_RGB332:
return 8;
case VIDEO_PIX_FMT_SBGGR10P:
case VIDEO_PIX_FMT_SGBRG10P:
Expand All @@ -1396,6 +1411,7 @@ static inline unsigned int video_bits_per_pixel(uint32_t pixfmt)
case VIDEO_PIX_FMT_Y14P:
return 14;
case VIDEO_PIX_FMT_RGB565:
case VIDEO_PIX_FMT_RGB565X:
case VIDEO_PIX_FMT_YUYV:
case VIDEO_PIX_FMT_YVYU:
case VIDEO_PIX_FMT_UYVY:
Expand All @@ -1419,6 +1435,7 @@ static inline unsigned int video_bits_per_pixel(uint32_t pixfmt)
return 16;
case VIDEO_PIX_FMT_BGR24:
case VIDEO_PIX_FMT_RGB24:
case VIDEO_PIX_FMT_YUV24:
return 24;
case VIDEO_PIX_FMT_XRGB32:
case VIDEO_PIX_FMT_XYUV32:
Expand Down
91 changes: 91 additions & 0 deletions include/zephyr/pixel/bayer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* Copyright (c) 2025 tinyVision.ai Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef ZEPHYR_INCLUDE_PIXEL_BAYER_H_
#define ZEPHYR_INCLUDE_PIXEL_BAYER_H_

#include <stdint.h>
#include <stdlib.h>

#include <zephyr/pixel/operation.h>

/**
* @brief Define a new bayer format conversion operation.
*
* @param _fn Function performing the operation.
* @param _fourcc_in The input format for that operation.
* @param _window_size The number of line of context needed for that debayer operation.
*/
#define PIXEL_DEFINE_BAYER_OPERATION(_fn, _fourcc_in, _window_size) \
static const STRUCT_SECTION_ITERABLE_ALTERNATE(pixel_convert, pixel_operation, \
_fn##_op) = { \
.name = #_fn, \
.fourcc_in = _fourcc_in, \
.fourcc_out = VIDEO_PIX_FMT_RGB24, \
.window_size = _window_size, \
.run = _fn, \
}

/**
* @brief Convert a line from RGGB8 to RGB24 with 3x3 method
*
* @param i0 Buffer of the input row number 0 in bayer format (1 byte per pixel).
* @param i1 Buffer of the input row number 1 in bayer format (1 byte per pixel).
* @param i2 Buffer of the input row number 2 in bayer format (1 byte per pixel).
* @param rgb24 Buffer of the output row in RGB24 format (3 bytes per pixel).
* @param width Width of the lines in number of pixels.
*/
void pixel_line_rggb8_to_rgb24_3x3(const uint8_t *i0, const uint8_t *i1, const uint8_t *i2,
uint8_t *rgb24, uint16_t width);
/**
* @brief Convert a line from GRBG8 to RGB24 with 3x3 method
* @copydetails pixel_line_rggb8_to_rgb24_3x3()
*/
void pixel_line_grbg8_to_rgb24_3x3(const uint8_t *i0, const uint8_t *i1, const uint8_t *i2,
uint8_t *rgb24, uint16_t width);
/**
* @brief Convert a line from BGGR8 to RGB24 with 3x3 method
* @copydetails pixel_line_rggb8_to_rgb24_3x3()
*/
void pixel_line_bggr8_to_rgb24_3x3(const uint8_t *i0, const uint8_t *i1, const uint8_t *i2,
uint8_t *rgb24, uint16_t width);
/**
* @brief Convert a line from GBRG8 to RGB24 with 3x3 method
* @copydetails pixel_line_rggb8_to_rgb24_3x3()
*/
void pixel_line_gbrg8_to_rgb24_3x3(const uint8_t *i0, const uint8_t *i1, const uint8_t *i2,
uint8_t *rgb24, uint16_t width);

/**
* @brief Convert a line from RGGB8 to RGB24 with 2x2 method
*
* @param i0 Buffer of the input row number 0 in bayer format (1 byte per pixel).
* @param i1 Buffer of the input row number 1 in bayer format (1 byte per pixel).
* @param rgb24 Buffer of the output row in RGB24 format (3 bytes per pixel).
* @param width Width of the lines in number of pixels.
*/
void pixel_line_rggb8_to_rgb24_2x2(const uint8_t *i0, const uint8_t *i1, uint8_t *rgb24,
uint16_t width);
/**
* @brief Convert a line from GBRG8 to RGB24 with 2x2 method
* @copydetails pixel_line_rggb8_to_rgb24_2x2()
*/
void pixel_line_gbrg8_to_rgb24_2x2(const uint8_t *i0, const uint8_t *i1, uint8_t *rgb24,
uint16_t width);
/**
* @brief Convert a line from BGGR8 to RGB24 with 2x2 method
* @copydetails pixel_line_rggb8_to_rgb24_2x2()
*/
void pixel_line_bggr8_to_rgb24_2x2(const uint8_t *i0, const uint8_t *i1, uint8_t *rgb24,
uint16_t width);
/**
* @brief Convert a line from GRBG8 to RGB24 with 2x2 method
* @copydetails pixel_line_rggb8_to_rgb24_2x2()
*/
void pixel_line_grbg8_to_rgb24_2x2(const uint8_t *i0, const uint8_t *i1, uint8_t *rgb24,
uint16_t width);

#endif /* ZEPHYR_INCLUDE_PIXEL_BAYER_H_ */
137 changes: 137 additions & 0 deletions include/zephyr/pixel/convert.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/*
* Copyright (c) 2025 tinyVision.ai Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef ZEPHYR_INCLUDE_PIXEL_CONVERT_H_
#define ZEPHYR_INCLUDE_PIXEL_CONVERT_H_

#include <stdlib.h>
#include <stdint.h>

#include <zephyr/sys/util.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/pixel/image.h>

/**
* @brief Define a new format conversion operation.
*
* @param _fn Function converting one input line.
* @param _fourcc_in The input format for that operation.
* @param _fourcc_out The Output format for that operation.
*/
#define PIXEL_DEFINE_CONVERT_OPERATION(_fn, _fourcc_in, _fourcc_out) \
static const STRUCT_SECTION_ITERABLE_ALTERNATE(pixel_convert, pixel_operation, \
_fn##_op) = { \
.name = #_fn, \
.fourcc_in = _fourcc_in, \
.fourcc_out = _fourcc_out, \
.window_size = 1, \
.run = pixel_convert_op, \
.arg = _fn, \
}
/**
* @brief Helper to turn a format conversion function into an operation.
*
* The line conversion function is free to perform any processing on the input line.
* The @c w argument is the width of both the source and destination buffers.
*
* The line conversion function is to be provided in @c op->arg
*
* @param op Current operation in progress.
*/
void pixel_convert_op(struct pixel_operation *op);

/**
* @brief Get the luminance (luma channel) of an RGB24 pixel.
*
* @param rgb24 Pointer to an RGB24 pixel: red, green, blue channels.
*/
uint8_t pixel_rgb24_get_luma_bt709(const uint8_t rgb24[3]);

/**
* @brief Convert a line of pixel data from RGB24 to RGB24 (null conversion).
*
* See @ref video_pixel_formats for the definition of the input and output formats.
*
* You only need to call this function to work directly on raw buffers.
* See @ref pixel_image_convert for converting between formats.
*
* @param src Buffer of the input line in the format, @c XXX in @c pixel_line_XXX_to_YYY().
* @param dst Buffer of the output line in the format, @c YYY in @c pixel_line_XXX_to_YYY().
* @param width Width of the lines in number of pixels.
*/
void pixel_line_rgb24_to_rgb24(const uint8_t *src, uint8_t *dst, uint16_t width);
/**
* @brief Convert a line of pixel data from RGB332 to RGB24.
* @copydetails pixel_line_rgb24_to_rgb24()
*/
void pixel_line_rgb332_to_rgb24(const uint8_t *src, uint8_t *dst, uint16_t width);
/**
* @brief Convert a line of pixel data from RGB24 to RGB332 little-endian.
* @copydetails pixel_line_rgb24_to_rgb24()
*/
void pixel_line_rgb24_to_rgb332(const uint8_t *src, uint8_t *dst, uint16_t width);
/**
* @brief Convert a line of pixel data from RGB565 little-endian to RGB24.
* @copydetails pixel_line_rgb24_to_rgb24()
*/
void pixel_line_rgb565le_to_rgb24(const uint8_t *src, uint8_t *dst, uint16_t width);
/**
* @brief Convert a line of pixel data from RGB565 big-endian to RGB24.
* @copydetails pixel_line_rgb24_to_rgb24()
*/
void pixel_line_rgb565be_to_rgb24(const uint8_t *src, uint8_t *dst, uint16_t width);
/**
* @brief Convert a line of pixel data from RGB24 to RGB565 little-endian.
* @copydetails pixel_line_rgb24_to_rgb24()
*/
void pixel_line_rgb24_to_rgb565le(const uint8_t *src, uint8_t *dst, uint16_t width);
/**
* @brief Convert a line of pixel data from RGB24 to RGB565 big-endian.
* @copydetails pixel_line_rgb24_to_rgb24()
*/
void pixel_line_rgb24_to_rgb565be(const uint8_t *src, uint8_t *dst, uint16_t width);
/**
* @brief Convert a line of pixel data from YUYV to RGB24 (BT.709 coefficients).
* @copydetails pixel_line_rgb24_to_rgb24()
*/
void pixel_line_yuyv_to_rgb24_bt709(const uint8_t *src, uint8_t *dst, uint16_t width);
/**
* @brief Convert a line of pixel data from RGB24 to YUYV (BT.709 coefficients).
* @copydetails pixel_line_rgb24_to_rgb24()
*/
void pixel_line_rgb24_to_yuyv_bt709(const uint8_t *src, uint8_t *dst, uint16_t width);
/**
* @brief Convert a line of pixel data from RGB24 to YUV24 (BT.709 coefficients).
* @copydetails pixel_line_rgb24_to_rgb24()
*/
void pixel_line_rgb24_to_yuv24_bt709(const uint8_t *src, uint8_t *dst, uint16_t width);
/**
* @brief Convert a line of pixel data from YUV24 to RGB24 (BT.709 coefficients).
* @copydetails pixel_line_rgb24_to_rgb24()
*/
void pixel_line_yuv24_to_rgb24_bt709(const uint8_t *src, uint8_t *dst, uint16_t width);
/**
* @brief Convert a line of pixel data from YUYV to YUV24
* @copydetails pixel_line_rgb24_to_rgb24()
*/
void pixel_line_yuyv_to_yuv24(const uint8_t *src, uint8_t *dst, uint16_t width);
/**
* @brief Convert a line of pixel data from YUV24 to YUYV
* @copydetails pixel_line_rgb24_to_rgb24()
*/
void pixel_line_yuv24_to_yuyv(const uint8_t *src, uint8_t *dst, uint16_t width);
/**
* @brief Convert a line of pixel data from Y8 to RGB24
* @copydetails pixel_line_rgb24_to_rgb24()
*/
void pixel_line_y8_to_rgb24_bt709(const uint8_t *src, uint8_t *dst, uint16_t width);
/**
* @brief Convert a line of pixel data from RGB24 to Y8
* @copydetails pixel_line_rgb24_to_rgb24()
*/
void pixel_line_rgb24_to_y8_bt709(const uint8_t *src, uint8_t *dst, uint16_t width);

#endif /* ZEPHYR_INCLUDE_PIXEL_CONVERT_H_ */
41 changes: 41 additions & 0 deletions include/zephyr/pixel/distort.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright (c) 2025 tinyVision.ai Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef ZEPHYR_INCLUDE_PIXEL_DISTORT_H_
#define ZEPHYR_INCLUDE_PIXEL_DISTORT_H_

/** Coordinates of a pixel in row and column */
struct pixel_pt {
/** Position through the vertical axis, incrementing from top to bottom */
int16_t row;
/** Position through the horizontal axis incrementing from left to right */
int16_t col;
};

/** Buffer of contiguous pixel data. */
struct pixel_buf {
/** Pointer to the buffer pixel data in a format known by the user. */
uint8_t *data;
/** Width of the image in pixels (not bytes) */
uint16_t width;
/** Height of the imager in pixels */
uint16_t height;
};

/** Grid of pixel coordinates. */
struct pixel_grid {
/* Point coordinates */
const struct pixel_pt *points;
/* Number of columns in the grid */
uint16_t width;
/* Number of rows in the grid */
uint16_t height;
};

void pixel_distort_raw8frame_to_raw8frame(struct pixel_buf *sbuf, struct pixel_buf *dbuf,
const struct pixel_grid *grid);

#endif /* ZEPHYR_INCLUDE_PIXEL_DISTORT_H_ */
Loading
Loading