使用goto语句对C ++块进行Python化

时间:2018-08-29 15:38:19

标签: python c++ goto

我一直在用Python编写C ++代码,遇到了一种被卡住的情况。程序员使用goto语句实现了自己的逻辑,并且由于Python中没有goto语句,并且由于我不想深入研究它的有趣的goto实现,所以我想知道是否可以通过某种方式对以下代码块进行Python化:

// 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);
        ...

他去了一个名为“ Jump”的标签。我们怎么能用Python来实现这一目标?由于我们已经处于for循环中,因此在引入更多循环方面有些犹豫。

谢谢。

编辑:感谢贡献者,提出了以下建议,但这陷入了无限循环:

# 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)

3 个答案:

答案 0 :(得分:4)

C ++代码需要重做:goto语句和索引增加等效于continue指令(在C /中,您几乎 几乎不需要goto C ++程序,并且肯定不在这里,是原始的C ++代码,其“模拟” continue,因为作者不知道它存在):

for (int j = 0; j < circle_radius_vec.size(); ++j)
    {   
        ..
        // If ROI is outside of image skip circle
        if(roi_corner_x < 0){continue;}

请注意,现在您无需手动增加索引,因为continue跳到下一个迭代,调用循环的++j

(incrementation + goto的另一个问题是,如果特殊情况发生在数组的末尾,那么您可以在数组的边界之外读取:未定义的行为

现在,您可以直接在python中转置它:您有2个选项:

要么使用索引(就像C ++代码一样)

for index in range(size):        
    ...
    if some_condition:
        continue

或仅对元素进行迭代(更多pythonic,因为它不使用索引):

for a in the_list:
    # a is the current element of the list, not the index
    ...
    if some_condition:
        continue

在两种情况下,for循环都控制迭代。您只需告诉python使用continue跳到下一个迭代,就像在“新” C ++代码中一样。

答案 1 :(得分:0)

由于所有跳转似乎都由j ++进行,并且跳转是循环的开始,因此Python继续语句似乎很容易解决您的问题?

# Loop over all detected circles of the input image
for in range(1, circle_radius_vec.size()):

    # Variables for ROI
    roi_height_width = 0
    roi_corner_x = 0
    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 or roi_corner_y < 0 or roi_corner_x + roi_height_width > input_img.cols or roi_corner_y + roi_height_width > input_img.rows:
        continue

    # Create ROI from input image
    Rect roi = Rect(roi_corner_x, roi_corner_y, roi_height_width, roi_height_width)
    img_roi = input_img(roi)

    # Create HSV representation of ROI
    hsv()
    cvtColor(img_roi, hsv, COLOR_BGR2HSV)
    ...

我个人只是将if语句反转并有条件地执行代码的下半部分,如下所示:

# Loop over all detected circles of the input image
for in range(1, circle_radius_vec.size()):

    # Variables for ROI
    roi_height_width = 0
    roi_corner_x = 0
    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 and roi_corner_y >= 0 and roi_corner_x + roi_height_width <= input_img.cols and roi_corner_y + roi_height_width <= input_img.rows:


        # Create ROI from input image
        Rect roi = Rect(roi_corner_x, roi_corner_y, roi_height_width, roi_height_width)
        img_roi = input_img(roi)

        # Create HSV representation of ROI
        hsv()
        cvtColor(img_roi, hsv, COLOR_BGR2HSV)
        ...

答案 2 :(得分:0)

好的。 我建议这个。

public class MyWindow : Window
{
    public MyWindow()
    {
        DetectForTabletMode();

        // Turn OFF auto-rotation for duration of my primary application window
        MyUser32.SetAutoRotation(false);

        // Hooks for detecting screen bounds / taskbar height impact to form
        // the "SystemEvents" is a static instance and always available.  I have added
        // so each window can adjust itself as needed.  I have actually hooked into
        // both User preferences and Display Settings
        SystemEvents.UserPreferenceChanged += MyWindow_DisplaySettingsChanged;
        SystemEvents.DisplaySettingsChanged += MyWindow_DisplaySettingsChanged;

        // hook to closed event so I can clean up when window is finished
        Closed += MyWindow_Closed;
    }

    private void MyWindow_Closed(object sender, EventArgs e)
    {
        // Disconnect event handler for detecting when in/out of tablet mode
        if(_tabletWatch != null )
        {
            _tabletWatch.EventArrived -= tabletWatch_EventArrived;
            _tabletWatch.Stop();
        }

        // When closing my main window, re-enable the auto-rotation
        MyUser32.SetAutoRotation(true);

        // Disable screen resolution impact to prevent memory leaks 
        // must release on closing window or memory leaks per MS documentation
        // https://docs.microsoft.com/en-us/dotnet/api/microsoft.win32.systemevents.displaysettingschanged?view=netframework-4.7.2
        SystemEvents.UserPreferenceChanged -= MyWindow_DisplaySettingsChanged;
        SystemEvents.DisplaySettingsChanged -= MyWindow_DisplaySettingsChanged;


        // under your control, probably only want to turn back on at the END of the APPLICATION
        // and not just all windows individually
        MyUser32.SetAutoRotation(true);

    }

    #region Detect / Set / Handle tablet mode

    private bool _inTabletMode;
    public bool InTabletMode
    {
        get { return _inTabletMode; }
        private set
        {
            _inTabletMode = value;
            // do anything you want when changing in/out of tablet mode
        }
    }

    private ManagementEventWatcher _tabletWatch;


    private void DetectForTabletMode()
    {
        var currentUser = WindowsIdentity.GetCurrent();
        // to capture event when user swaps between normal and tablet modes.
        if (currentUser != null && currentUser.User != null)
        {
            var wqlEventQuery = new EventQuery( string.Format(
                @"SELECT * 
                    FROM 
                        RegistryValueChangeEvent 
                    WHERE 
                            Hive='HKEY_USERS' 
                        AND KeyPath='{0}\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\ImmersiveShell' 
                        AND ValueName='TabletMode'", currentUser.User.Value ));

            _tabletWatch = new ManagementEventWatcher(wqlEventQuery);
            _tabletWatch.EventArrived += tabletWatch_EventArrived;
            _tabletWatch.Start();
        }
    }

    private void tabletWatch_EventArrived(object sender, EventArrivedEventArgs e)
    {
        Dispatcher.Invoke(() =>
        {
            InTabletMode = 1 == (int)Registry.GetValue("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\ImmersiveShell", "TabletMode", 0);
        });
    }

    #endregion Detect / Set / Handle tablet mode

    #region Display and Orientation settings
    private System.Drawing.Rectangle _lastDimensions;

    // typical mode is landscape such as desktop / notbook mode anyhow.
    private bool _isLandscapeMode = true;   
    public bool IsLandscapeMode { get { return _isLandscapeMode; } }

    private bool _isPortraitMode { get { return !_isLandscapeMode; } }
    public bool IsPortraitMode { get { return _isPortraitMode; } }


    private void MyWindow_DisplaySettingsChanged(object sender, EventArgs e)
    {
        // get WINDOWS primary screen boundary dimensions
        var psb = System.Windows.Forms.Screen.PrimaryScreen.Bounds;

        // only if coming in and different than a previous setting
        if (_lastDimensions != null)
        {
            // Compare height and width of screen and act accordingly for orientation
            _isLandscapeMode = (psb.Height < psb.Width);

            // did dimensions change, such as from height of taskbar area shrinking
            // available real estate for YOUR Window.
            if (_lastDimensions.Height == psb.Height
                && _lastDimensions.Width == psb.Width)
                // same dimensions, get out, nothing more to do...
                return;

            // allow virtual method per form to handle itself as needed
            // and pass in the new dimensions.
            WinDimensionsChanged(psb);
        }
        // always preserve latest dimensions IN-CASE changes, such as taskbar, etc..
        _lastDimensions = psb;
    }

    protected virtual void WinDimensionsChanged(System.Drawing.Rectangle newestDimensions)
    {
        // do whatever you want per child-declared window

    }

    #endregion Display and Orientation settings

}

由于我不了解其余代码,因此我不太准确。 请告诉我是否发生任何错误。

相关问题