Skip to content

Commit e98482a

Browse files
committed
Add imread()
1 parent e2f0fc6 commit e98482a

File tree

4 files changed

+108
-0
lines changed

4 files changed

+108
-0
lines changed

src/imgcodecs.cpp

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// C++ headers
2+
#include "opencv2/core.hpp"
3+
#include "opencv2/imgcodecs.hpp"
4+
#include "convert.h"
5+
#include "numpy.h"
6+
7+
// C headers
8+
extern "C" {
9+
#include "imgcodecs.h"
10+
#include "ulab/code/ndarray.h"
11+
#include "py/builtin.h"
12+
} // extern "C"
13+
14+
using namespace cv;
15+
16+
// Helper macro to create an empty mp_map_t, derived from MP_DEFINE_CONST_MAP.
17+
// Primarily used for function calls with no keyword arguments, since we can't
18+
// just pass `NULL` or mp_const_none (crash occurs otherwise)
19+
#define MP_EMPTY_MAP() { \
20+
.all_keys_are_qstrs = 0, \
21+
.is_fixed = 1, \
22+
.is_ordered = 0, \
23+
.used = 0, \
24+
.alloc = 0, \
25+
.table = (mp_map_elem_t *)(mp_rom_map_elem_t *)mp_const_none, \
26+
}
27+
28+
mp_obj_t cv2_imgcodecs_imread(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
29+
// Define the arguments
30+
enum { ARG_filename, ARG_flags };
31+
static const mp_arg_t allowed_args[] = {
32+
{ MP_QSTR_filename, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = MP_OBJ_NULL } },
33+
{ MP_QSTR_flags, MP_ARG_INT, { .u_int = IMREAD_COLOR_BGR } },
34+
};
35+
36+
// Parse the arguments
37+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
38+
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
39+
40+
// Convert arguments to required types
41+
mp_obj_t filename = args[ARG_filename].u_obj;
42+
int flags = args[ARG_flags].u_int;
43+
44+
// Call MicroPython's `open()` function to read the image file
45+
mp_obj_t open_args[2];
46+
open_args[0] = filename;
47+
open_args[1] = mp_obj_new_str("rb", 2); // Open in binary read mode
48+
mp_map_t open_kw_args = MP_EMPTY_MAP(); // No keyword arguments
49+
mp_obj_t file_obj = mp_builtin_open(2, open_args, &open_kw_args);
50+
51+
// Call the `read()` method on the file object to get the image data
52+
mp_obj_t read_method[2];
53+
mp_load_method(file_obj, MP_QSTR_read, read_method);
54+
mp_obj_t bytes_obj = mp_call_method_n_kw(0, 0, read_method);
55+
56+
// Close the file object
57+
mp_obj_t close_method[2];
58+
mp_load_method(file_obj, MP_QSTR_close, close_method);
59+
mp_call_method_n_kw(0, 0, close_method);
60+
61+
// Convert bytes_obj to vector of uint8_t for decoding
62+
size_t len;
63+
const char *buf_data = mp_obj_str_get_data(bytes_obj, &len);
64+
std::vector<uint8_t> buf(buf_data, buf_data + len);
65+
66+
// Decode the image from the buffer
67+
Mat img;
68+
try {
69+
img = imdecode(buf, flags);
70+
} catch(Exception& e) {
71+
mp_raise_msg(&mp_type_Exception, MP_ERROR_TEXT(e.what()));
72+
}
73+
74+
// Return the image
75+
return mat_to_mp_obj(img);
76+
}

src/imgcodecs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// C headers
2+
#include "py/runtime.h"
3+
4+
extern mp_obj_t cv2_imgcodecs_imread(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);

src/opencv_upy.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "core.h"
22
#include "highgui.h"
33
#include "imgproc.h"
4+
#include "imgcodecs.h"
45

56
////////////////////////////////////////////////////////////////////////////////
67
// Python references to OpenCV functions
@@ -14,6 +15,9 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(cv2_core_inRange_obj, 3, cv2_core_inRange);
1415
static MP_DEFINE_CONST_FUN_OBJ_KW(cv2_highgui_imshow_obj, 2, cv2_highgui_imshow);
1516
static MP_DEFINE_CONST_FUN_OBJ_KW(cv2_highgui_waitKey_obj, 0, cv2_highgui_waitKey);
1617

18+
// OpenCV imgcodecs module
19+
static MP_DEFINE_CONST_FUN_OBJ_KW(cv2_imgcodecs_imread_obj, 1, cv2_imgcodecs_imread);
20+
1721
// OpenCV imgproc module
1822
static MP_DEFINE_CONST_FUN_OBJ_KW(cv2_imgproc_adaptiveThreshold_obj, 6, cv2_imgproc_adaptiveThreshold);
1923
static MP_DEFINE_CONST_FUN_OBJ_KW(cv2_imgproc_arrowedLine_obj, 4, cv2_imgproc_arrowedLine);
@@ -88,6 +92,23 @@ static const mp_rom_map_elem_t cv2_module_globals_table[] = {
8892
{ MP_ROM_QSTR(MP_QSTR_BORDER_DEFAULT), MP_ROM_INT(4) },
8993
{ MP_ROM_QSTR(MP_QSTR_BORDER_ISOLATED), MP_ROM_INT(16) },
9094

95+
// Image read mode flags, from opencv2/imgcodecs.hpp
96+
{ MP_ROM_QSTR(MP_QSTR_IMREAD_UNCHANGED), MP_ROM_INT(-1) },
97+
{ MP_ROM_QSTR(MP_QSTR_IMREAD_GRAYSCALE), MP_ROM_INT(0) },
98+
{ MP_ROM_QSTR(MP_QSTR_IMREAD_COLOR_BGR), MP_ROM_INT(1) },
99+
{ MP_ROM_QSTR(MP_QSTR_IMREAD_COLOR), MP_ROM_INT(1) },
100+
{ MP_ROM_QSTR(MP_QSTR_IMREAD_ANYDEPTH), MP_ROM_INT(2) },
101+
{ MP_ROM_QSTR(MP_QSTR_IMREAD_ANYCOLOR), MP_ROM_INT(4) },
102+
{ MP_ROM_QSTR(MP_QSTR_IMREAD_LOAD_GDAL), MP_ROM_INT(8) },
103+
{ MP_ROM_QSTR(MP_QSTR_IMREAD_REDUCED_GRAYSCALE_2), MP_ROM_INT(16) },
104+
{ MP_ROM_QSTR(MP_QSTR_IMREAD_REDUCED_COLOR_2), MP_ROM_INT(17) },
105+
{ MP_ROM_QSTR(MP_QSTR_IMREAD_REDUCED_GRAYSCALE_4), MP_ROM_INT(32) },
106+
{ MP_ROM_QSTR(MP_QSTR_IMREAD_REDUCED_COLOR_4), MP_ROM_INT(33) },
107+
{ MP_ROM_QSTR(MP_QSTR_IMREAD_REDUCED_GRAYSCALE_8), MP_ROM_INT(64) },
108+
{ MP_ROM_QSTR(MP_QSTR_IMREAD_REDUCED_COLOR_8), MP_ROM_INT(65) },
109+
{ MP_ROM_QSTR(MP_QSTR_IMREAD_IGNORE_ORIENTATION), MP_ROM_INT(128) },
110+
{ MP_ROM_QSTR(MP_QSTR_IMREAD_COLOR_RGB), MP_ROM_INT(256) },
111+
91112
// Morphology operation types, from opencv2/imgproc.hpp
92113
{ MP_ROM_QSTR(MP_QSTR_MORPH_ERODE), MP_ROM_INT(0) },
93114
{ MP_ROM_QSTR(MP_QSTR_MORPH_DILATE), MP_ROM_INT(1) },
@@ -223,6 +244,12 @@ static const mp_rom_map_elem_t cv2_module_globals_table[] = {
223244

224245
{ MP_ROM_QSTR(MP_QSTR_imshow), MP_ROM_PTR(&cv2_highgui_imshow_obj) },
225246
{ MP_ROM_QSTR(MP_QSTR_waitKey), MP_ROM_PTR(&cv2_highgui_waitKey_obj) },
247+
248+
////////////////////////////////////////////////////////////////////////////
249+
// OpenCV imgcodecs functions
250+
////////////////////////////////////////////////////////////////////////////
251+
252+
{ MP_ROM_QSTR(MP_QSTR_imread), MP_ROM_PTR(&cv2_imgcodecs_imread_obj) },
226253

227254
////////////////////////////////////////////////////////////////////////////
228255
// OpenCV imgproc functions

src/opencv_upy.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ target_sources(usermod_cv2 INTERFACE
77
${CMAKE_CURRENT_LIST_DIR}/convert.cpp
88
${CMAKE_CURRENT_LIST_DIR}/core.cpp
99
${CMAKE_CURRENT_LIST_DIR}/highgui.cpp
10+
${CMAKE_CURRENT_LIST_DIR}/imgcodecs.cpp
1011
${CMAKE_CURRENT_LIST_DIR}/imgproc.cpp
1112
${CMAKE_CURRENT_LIST_DIR}/numpy.cpp
1213
${CMAKE_CURRENT_LIST_DIR}/opencv_upy.c

0 commit comments

Comments
 (0)