I have been Pythonising a C++ code and I came across a situation in which I kinda got stuck. The programmer used goto statements to implement his logic, and since there is no goto statement in Python and since I'd rather not to delve into funny goto implementations of it, I was wondering if we could somehow Pythonize the following block:
// Loop over all detected circles of the input image
for (int j = 0; j < circle_radius_vec.size(); ++j)
{
Jump:
// Variables for ROI
int roi_height_width = 0;
int roi_corner_x = 0;
int roi_corner_y = 0;
Point center_now(roi_height_width/2, roi_height_width/2);
// Load aktuellen center point
center_now = center_vec[j];
// Calculate ROI
roi_height_width = circle_radius_vec[j];
roi_corner_x = center_now.x - roi_height_width/2;
roi_corner_y = center_now.y - roi_height_width/2;
// If ROI is outside of image skip circle
if(roi_corner_x < 0){j++; goto Jump;}
if(roi_corner_y < 0){j++; goto Jump;}
if((roi_corner_x+roi_height_width) > input_img.cols){j++; goto Jump;}
if((roi_corner_y+roi_height_width) > input_img.rows){j++; goto Jump;}
// Create ROI from input image
Rect roi = Rect(roi_corner_x, roi_corner_y, roi_height_width, roi_height_width);
Mat img_roi = input_img(roi);
// Create HSV representation of ROI
Mat hsv;
cvtColor(img_roi, hsv, COLOR_BGR2HSV);
...
He has the label called "Jump" to which he goes to. How could we Pythonize this one? Since we are already in a for loop, I am a bit hesistant to introduce more loops.
Thanks in advance.
EDIT: Thanks to the contributors, the following was suggested, however this gets stuck in an infinite loop:
# Loop over all detected circles of the input image
for j in range(len(center_vec)):
while True:
# arrange the ROI
# load the current center point
center_now = center_vec[j] # take the center of ROI as the center of circle
roi_height_width = int(round(circle_radius_vec[j])) # take the radius as height and width of the ROI
roi_height_width = int(round(circle_radius_vec[j]))
roi_corner_x = int(round(center_now[0] - roi_height_width / 2))
roi_corner_y = int(round(center_now[1] - roi_height_width / 2))
# If ROI is outside of image skip circle
if roi_corner_x < 0:
j += 1
continue
if roi_corner_y < 0:
j += 1
continue
if roi_corner_x + roi_height_width > img.shape[1]:
j += 1
continue
if roi_corner_y + roi_height_width > img.shape[0]:
j += 1
continue
# create ROI from input image Rect
roi = img[roi_corner_y:roi_corner_y+roi_height_width, roi_corner_x:roi_corner_x+roi_height_width]
# Create HSV representation of ROI
hsv = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)
The C++ code needs rework: the goto
statement and index increase is equivalent to a continue
instruction (you almost never need goto
in a C/C++ program, and definitely not here, the original C++ code which is "emulating" continue
because the author didn't know that it existed):
for (int j = 0; j < circle_radius_vec.size(); ++j)
{
..
// If ROI is outside of image skip circle
if(roi_corner_x < 0){continue;}
Note that now you don't need to increase manually the index, as continue
skips to the next iteration, calling the ++j
of your loop.
(the other issue of the incrementation+goto is that if the special case happens at the end of the array, then you can read outside the bounds of the array: undefined behaviour)
Now, you can transpose that directly in python: you have 2 options:
Either you go with indices (like your C++ code does)
for index in range(size):
...
if some_condition:
continue
or just iterate on elements (more pythonic, because it doesn't use indices):
for a in the_list:
# a is the current element of the list, not the index
...
if some_condition:
continue
In both cases, the for
loop controls the iteration. You just tell python to skip to the next iteration with continue
, just like in the "new" C++ code.