Skip to content

Commit f4f776d

Browse files
committed
Add Canny and Hough functions
HoughLinesP uses int32 for the output array, which ulab currenltly does not support. Commented out for now.
1 parent 4cf886d commit f4f776d

File tree

3 files changed

+348
-1
lines changed

3 files changed

+348
-1
lines changed

src/imgproc.cpp

Lines changed: 322 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,41 @@ mp_obj_t cv2_imgproc_arrowedLine(size_t n_args, const mp_obj_t *pos_args, mp_map
5555
return mat_to_mp_obj(img);
5656
}
5757

58+
mp_obj_t cv2_imgproc_Canny(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
59+
// Define the arguments
60+
enum { ARG_image, ARG_threshold1, ARG_threshold2, ARG_edges, ARG_apertureSize, ARG_L2gradient };
61+
static const mp_arg_t allowed_args[] = {
62+
{ MP_QSTR_image, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = MP_OBJ_NULL } },
63+
{ MP_QSTR_threshold1, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } },
64+
{ MP_QSTR_threshold2, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } },
65+
{ MP_QSTR_edges, MP_ARG_OBJ, { .u_obj = mp_const_none } },
66+
{ MP_QSTR_apertureSize, MP_ARG_INT, { .u_int = 3 } },
67+
{ MP_QSTR_L2gradient, MP_ARG_BOOL, { .u_bool = false } },
68+
};
69+
70+
// Parse the arguments
71+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
72+
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
73+
74+
// Convert arguments to required types
75+
Mat image = mp_obj_to_mat(args[ARG_image].u_obj);
76+
int threshold1 = args[ARG_threshold1].u_int;
77+
int threshold2 = args[ARG_threshold2].u_int;
78+
Mat edges = mp_obj_to_mat(args[ARG_edges].u_obj);
79+
int apertureSize = args[ARG_apertureSize].u_int;
80+
bool L2gradient = args[ARG_L2gradient].u_bool;
81+
82+
// Call the corresponding OpenCV function
83+
try {
84+
Canny(image, edges, threshold1, threshold2, apertureSize, L2gradient);
85+
} catch(Exception& e) {
86+
mp_raise_msg(&mp_type_Exception, MP_ERROR_TEXT(e.what()));
87+
}
88+
89+
// Return the result
90+
return mat_to_mp_obj(edges);
91+
}
92+
5893
mp_obj_t cv2_imgproc_circle(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
5994
// Define the arguments
6095
enum { ARG_img, ARG_center, ARG_radius, ARG_color, ARG_thickness, ARG_lineType, ARG_shift };
@@ -409,6 +444,293 @@ mp_obj_t cv2_imgproc_getStructuringElement(size_t n_args, const mp_obj_t *pos_ar
409444
return mat_to_mp_obj(kernel);
410445
}
411446

447+
mp_obj_t cv2_imgproc_HoughCircles(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
448+
// Define the arguments
449+
enum { ARG_image, ARG_method, ARG_dp, ARG_minDist, ARG_circles, ARG_param1, ARG_param2, ARG_minRadius, ARG_maxRadius };
450+
static const mp_arg_t allowed_args[] = {
451+
{ MP_QSTR_image, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = MP_OBJ_NULL } },
452+
{ MP_QSTR_method, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } },
453+
{ MP_QSTR_dp, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } },
454+
{ MP_QSTR_minDist, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } },
455+
{ MP_QSTR_circles, MP_ARG_OBJ, { .u_obj = mp_const_none } },
456+
{ MP_QSTR_param1, MP_ARG_OBJ, { .u_obj = mp_const_none } },
457+
{ MP_QSTR_param2, MP_ARG_OBJ, { .u_obj = mp_const_none } },
458+
{ MP_QSTR_minRadius, MP_ARG_INT, { .u_int = 0 } },
459+
{ MP_QSTR_maxRadius, MP_ARG_INT, { .u_int = 0 } },
460+
};
461+
462+
// Parse the arguments
463+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
464+
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
465+
466+
// Convert arguments to required types
467+
Mat image = mp_obj_to_mat(args[ARG_image].u_obj);
468+
int method = args[ARG_method].u_int;
469+
mp_float_t dp = mp_obj_get_float(args[ARG_dp].u_obj);
470+
mp_float_t minDist = mp_obj_get_float(args[ARG_minDist].u_obj);
471+
Mat circles = mp_obj_to_mat(args[ARG_circles].u_obj);
472+
float param1;
473+
if(args[ARG_param1].u_obj == mp_const_none)
474+
param1 = 100; // Default value
475+
else
476+
param1 = mp_obj_get_float(args[ARG_param1].u_obj);
477+
float param2;
478+
if(args[ARG_param2].u_obj == mp_const_none)
479+
param2 = 100; // Default value
480+
else
481+
param2 = mp_obj_get_float(args[ARG_param2].u_obj);
482+
int minRadius = args[ARG_minRadius].u_int;
483+
int maxRadius = args[ARG_maxRadius].u_int;
484+
485+
// Call the corresponding OpenCV function
486+
try {
487+
HoughCircles(image, circles, method, dp, minDist, param1, param2, minRadius, maxRadius);
488+
} catch(Exception& e) {
489+
mp_raise_msg(&mp_type_Exception, MP_ERROR_TEXT(e.what()));
490+
}
491+
492+
// Return the result
493+
return mat_to_mp_obj(circles);
494+
}
495+
496+
mp_obj_t cv2_imgproc_HoughCirclesWithAccumulator(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
497+
// Define the arguments
498+
enum { ARG_image, ARG_method, ARG_dp, ARG_minDist, ARG_circles, ARG_param1, ARG_param2, ARG_minRadius, ARG_maxRadius };
499+
static const mp_arg_t allowed_args[] = {
500+
{ MP_QSTR_image, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = MP_OBJ_NULL } },
501+
{ MP_QSTR_method, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } },
502+
{ MP_QSTR_dp, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } },
503+
{ MP_QSTR_minDist, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } },
504+
{ MP_QSTR_circles, MP_ARG_OBJ, { .u_obj = mp_const_none } },
505+
{ MP_QSTR_param1, MP_ARG_OBJ, { .u_obj = mp_const_none } },
506+
{ MP_QSTR_param2, MP_ARG_OBJ, { .u_obj = mp_const_none } },
507+
{ MP_QSTR_minRadius, MP_ARG_INT, { .u_int = 0 } },
508+
{ MP_QSTR_maxRadius, MP_ARG_INT, { .u_int = 0 } },
509+
};
510+
511+
// Parse the arguments
512+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
513+
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
514+
515+
// Convert arguments to required types
516+
Mat image = mp_obj_to_mat(args[ARG_image].u_obj);
517+
int method = args[ARG_method].u_int;
518+
mp_float_t dp = mp_obj_get_float(args[ARG_dp].u_obj);
519+
mp_float_t minDist = mp_obj_get_float(args[ARG_minDist].u_obj);
520+
Mat circles = mp_obj_to_mat(args[ARG_circles].u_obj);
521+
float param1;
522+
if(args[ARG_param1].u_obj == mp_const_none)
523+
param1 = 100; // Default value
524+
else
525+
param1 = mp_obj_get_float(args[ARG_param1].u_obj);
526+
float param2;
527+
if(args[ARG_param2].u_obj == mp_const_none)
528+
param2 = 100; // Default value
529+
else
530+
param2 = mp_obj_get_float(args[ARG_param2].u_obj);
531+
int minRadius = args[ARG_minRadius].u_int;
532+
int maxRadius = args[ARG_maxRadius].u_int;
533+
534+
// Vector to hold the circles and votes
535+
std::vector<Vec4f> circles_acc;
536+
537+
// Call the corresponding OpenCV function
538+
try {
539+
HoughCircles(image, circles_acc, method, dp, minDist, param1, param2, minRadius, maxRadius);
540+
} catch(Exception& e) {
541+
mp_raise_msg(&mp_type_Exception, MP_ERROR_TEXT(e.what()));
542+
}
543+
544+
// Copy the vector of circles and votes to output circles object
545+
Mat(circles_acc).copyTo(circles);
546+
547+
// Return the result
548+
return mat_to_mp_obj(circles);
549+
}
550+
551+
mp_obj_t cv2_imgproc_HoughLines(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
552+
// Define the arguments
553+
enum { ARG_image, ARG_rho, ARG_theta, ARG_threshold, ARG_lines, ARG_srn, ARG_stn, ARG_min_theta, ARG_max_theta, ARG_use_edgeval };
554+
static const mp_arg_t allowed_args[] = {
555+
{ MP_QSTR_image, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = MP_OBJ_NULL } },
556+
{ MP_QSTR_rho, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } },
557+
{ MP_QSTR_theta, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } },
558+
{ MP_QSTR_threshold, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 100 } },
559+
{ MP_QSTR_lines, MP_ARG_OBJ, { .u_obj = mp_const_none } },
560+
{ MP_QSTR_srn, MP_ARG_OBJ, { .u_obj = mp_const_none } },
561+
{ MP_QSTR_stn, MP_ARG_OBJ, { .u_obj = mp_const_none } },
562+
{ MP_QSTR_min_theta, MP_ARG_OBJ, { .u_obj = mp_const_none } },
563+
{ MP_QSTR_max_theta, MP_ARG_OBJ, { .u_obj = mp_const_none } },
564+
{ MP_QSTR_use_edgeval, MP_ARG_BOOL, { .u_bool = false } },
565+
};
566+
567+
// Parse the arguments
568+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
569+
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
570+
571+
// Convert arguments to required types
572+
Mat image = mp_obj_to_mat(args[ARG_image].u_obj);
573+
mp_float_t rho;
574+
if(args[ARG_rho].u_obj == mp_const_none)
575+
rho = 1; // Default value
576+
else
577+
rho = mp_obj_get_float(args[ARG_rho].u_obj);
578+
mp_float_t theta;
579+
if(args[ARG_theta].u_obj == mp_const_none)
580+
theta = CV_PI / 180; // Default value
581+
else
582+
theta = mp_obj_get_float(args[ARG_theta].u_obj);
583+
int threshold = args[ARG_threshold].u_int;
584+
Mat lines = mp_obj_to_mat(args[ARG_lines].u_obj);
585+
mp_float_t srn;
586+
if(args[ARG_srn].u_obj == mp_const_none)
587+
srn = 0; // Default value
588+
else
589+
srn = mp_obj_get_float(args[ARG_srn].u_obj);
590+
mp_float_t stn;
591+
if(args[ARG_stn].u_obj == mp_const_none)
592+
stn = 0; // Default value
593+
else
594+
stn = mp_obj_get_float(args[ARG_stn].u_obj);
595+
mp_float_t min_theta;
596+
if(args[ARG_min_theta].u_obj == mp_const_none)
597+
min_theta = 0; // Default value
598+
else
599+
min_theta = mp_obj_get_float(args[ARG_min_theta].u_obj);
600+
mp_float_t max_theta;
601+
if(args[ARG_max_theta].u_obj == mp_const_none)
602+
max_theta = CV_PI; // Default value
603+
else
604+
max_theta = mp_obj_get_float(args[ARG_max_theta].u_obj);
605+
bool use_edgeval = args[ARG_use_edgeval].u_bool;
606+
607+
// Call the corresponding OpenCV function
608+
try {
609+
HoughLines(image, lines, rho, theta, threshold, srn, stn, min_theta, max_theta, use_edgeval);
610+
} catch(Exception& e) {
611+
mp_raise_msg(&mp_type_Exception, MP_ERROR_TEXT(e.what()));
612+
}
613+
614+
// Return the result
615+
return mat_to_mp_obj(lines);
616+
}
617+
618+
// mp_obj_t cv2_imgproc_HoughLinesP(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
619+
// // Define the arguments
620+
// enum { ARG_image, ARG_rho, ARG_theta, ARG_threshold, ARG_lines, ARG_minLineLength, ARG_maxLineGap };
621+
// static const mp_arg_t allowed_args[] = {
622+
// { MP_QSTR_image, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = MP_OBJ_NULL } },
623+
// { MP_QSTR_rho, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } },
624+
// { MP_QSTR_theta, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } },
625+
// { MP_QSTR_threshold, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 100 } },
626+
// { MP_QSTR_lines, MP_ARG_OBJ, { .u_obj = mp_const_none } },
627+
// { MP_QSTR_minLineLength, MP_ARG_OBJ, { .u_obj = mp_const_none } },
628+
// { MP_QSTR_maxLineGap, MP_ARG_OBJ, { .u_obj = mp_const_none } },
629+
// };
630+
631+
// // Parse the arguments
632+
// mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
633+
// mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
634+
635+
// // Convert arguments to required types
636+
// Mat image = mp_obj_to_mat(args[ARG_image].u_obj);
637+
// mp_float_t rho = mp_obj_get_float(args[ARG_rho].u_obj);
638+
// mp_float_t theta = mp_obj_get_float(args[ARG_theta].u_obj);
639+
// int threshold = args[ARG_threshold].u_int;
640+
// Mat lines = mp_obj_to_mat(args[ARG_lines].u_obj);
641+
// mp_float_t minLineLength;
642+
// if(args[ARG_minLineLength].u_obj == mp_const_none)
643+
// minLineLength = 0; // Default value
644+
// else
645+
// minLineLength = mp_obj_get_float(args[ARG_minLineLength].u_obj);
646+
// mp_float_t maxLineGap;
647+
// if(args[ARG_maxLineGap].u_obj == mp_const_none)
648+
// maxLineGap = 0; // Default value
649+
// else
650+
// maxLineGap = mp_obj_get_float(args[ARG_maxLineGap].u_obj);
651+
652+
// // Call the corresponding OpenCV function
653+
// try {
654+
// HoughLinesP(image, lines, rho, theta, threshold, minLineLength, maxLineGap);
655+
// } catch(Exception& e) {
656+
// mp_raise_msg(&mp_type_Exception, MP_ERROR_TEXT(e.what()));
657+
// }
658+
659+
// // Return the result
660+
// return mat_to_mp_obj(lines);
661+
// }
662+
663+
mp_obj_t cv2_imgproc_HoughLinesWithAccumulator(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
664+
// Define the arguments
665+
enum { ARG_image, ARG_rho, ARG_theta, ARG_threshold, ARG_lines, ARG_srn, ARG_stn, ARG_min_theta, ARG_max_theta };
666+
static const mp_arg_t allowed_args[] = {
667+
{ MP_QSTR_image, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = MP_OBJ_NULL } },
668+
{ MP_QSTR_rho, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } },
669+
{ MP_QSTR_theta, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } },
670+
{ MP_QSTR_threshold, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 100 } },
671+
{ MP_QSTR_lines, MP_ARG_OBJ, { .u_obj = mp_const_none } },
672+
{ MP_QSTR_srn, MP_ARG_OBJ, { .u_obj = mp_const_none } },
673+
{ MP_QSTR_stn, MP_ARG_OBJ, { .u_obj = mp_const_none } },
674+
{ MP_QSTR_min_theta, MP_ARG_OBJ, { .u_obj = mp_const_none } },
675+
{ MP_QSTR_max_theta, MP_ARG_OBJ, { .u_obj = mp_const_none } },
676+
};
677+
678+
// Parse the arguments
679+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
680+
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
681+
682+
// Convert arguments to required types
683+
Mat image = mp_obj_to_mat(args[ARG_image].u_obj);
684+
mp_float_t rho;
685+
if(args[ARG_rho].u_obj == mp_const_none)
686+
rho = 1; // Default value
687+
else
688+
rho = mp_obj_get_float(args[ARG_rho].u_obj);
689+
mp_float_t theta;
690+
if(args[ARG_theta].u_obj == mp_const_none)
691+
theta = CV_PI / 180; // Default value
692+
else
693+
theta = mp_obj_get_float(args[ARG_theta].u_obj);
694+
int threshold = args[ARG_threshold].u_int;
695+
Mat lines = mp_obj_to_mat(args[ARG_lines].u_obj);
696+
mp_float_t srn;
697+
if(args[ARG_srn].u_obj == mp_const_none)
698+
srn = 0; // Default value
699+
else
700+
srn = mp_obj_get_float(args[ARG_srn].u_obj);
701+
mp_float_t stn;
702+
if(args[ARG_stn].u_obj == mp_const_none)
703+
stn = 0; // Default value
704+
else
705+
stn = mp_obj_get_float(args[ARG_stn].u_obj);
706+
mp_float_t min_theta;
707+
if(args[ARG_min_theta].u_obj == mp_const_none)
708+
min_theta = 0; // Default value
709+
else
710+
min_theta = mp_obj_get_float(args[ARG_min_theta].u_obj);
711+
mp_float_t max_theta;
712+
if(args[ARG_max_theta].u_obj == mp_const_none)
713+
max_theta = CV_PI; // Default value
714+
else
715+
max_theta = mp_obj_get_float(args[ARG_max_theta].u_obj);
716+
717+
// Vector to hold the lines and votes
718+
std::vector<Vec3f> lines_acc;
719+
720+
// Call the corresponding OpenCV function
721+
try {
722+
HoughLines(image, lines_acc, rho, theta, threshold, srn, stn, min_theta, max_theta);
723+
} catch(Exception& e) {
724+
mp_raise_msg(&mp_type_Exception, MP_ERROR_TEXT(e.what()));
725+
}
726+
727+
// Copy the vector of lines and votes to output lines object
728+
Mat(lines_acc).copyTo(lines);
729+
730+
// Return the result
731+
return mat_to_mp_obj(lines);
732+
}
733+
412734
mp_obj_t cv2_imgproc_line(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
413735
// Define the arguments
414736
enum { ARG_img, ARG_pt1, ARG_pt2, ARG_color, ARG_thickness, ARG_lineType, ARG_shift };

src/imgproc.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "py/runtime.h"
33

44
extern mp_obj_t cv2_imgproc_arrowedLine(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
5+
extern mp_obj_t cv2_imgproc_Canny(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
56
extern mp_obj_t cv2_imgproc_circle(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
67
extern mp_obj_t cv2_imgproc_cvtColor(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
78
extern mp_obj_t cv2_imgproc_dilate(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
@@ -11,6 +12,11 @@ extern mp_obj_t cv2_imgproc_erode(size_t n_args, const mp_obj_t *pos_args, mp_ma
1112
extern mp_obj_t cv2_imgproc_fillConvexPoly(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
1213
extern mp_obj_t cv2_imgproc_fillPoly(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
1314
extern mp_obj_t cv2_imgproc_getStructuringElement(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
15+
extern mp_obj_t cv2_imgproc_HoughCircles(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
16+
extern mp_obj_t cv2_imgproc_HoughCirclesWithAccumulator(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
17+
extern mp_obj_t cv2_imgproc_HoughLines(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
18+
// extern mp_obj_t cv2_imgproc_HoughLinesP(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
19+
extern mp_obj_t cv2_imgproc_HoughLinesWithAccumulator(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
1420
extern mp_obj_t cv2_imgproc_line(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
1521
extern mp_obj_t cv2_imgproc_morphologyEx(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
1622
extern mp_obj_t cv2_imgproc_putText(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);

0 commit comments

Comments
 (0)