Search code examples
pythonc++goto

Pythonizing C++ block with goto statement


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)

Solution

  • 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.