python - 如何仅提取图像的圆形 ROI 部分并通过在 Python OpenCV GUI 的 Tkinter 窗口中单击按钮来显示圆的半径

标签 python opencv user-interface tkinter roi

提取圆形 ROI 并在 Tkinter 标签中显示圆形的半径

我正在向这个社区的 python 专家请求帮助。我已经在 Stackexchange 以及 Github 社区中搜索了我的问题。但我没有发现任何有用的东西。
我创建了一个 Tkinter GUI。在这个 GUI 中,我可以从目标文件夹上传我的图像。在评估部分的选择中,我编写了一个脚本,通过它可以自动查看圆形部分的 ROI 区域。 GUI 显示在此问题的底部。

需要帮助部分 :我在创建脚本时遇到了麻烦,通过该脚本:

  • 当我点击 上传投资返回按钮,仅选定的 ROI 部分
    图像保存在目标文件夹,即 路径 =
    '数据/图像/' + 名称 + '_' + 方法 + 分机
  • 我可以在 Tkinter GUI 的某处查看圆的半径。

  • def ROI(self, image, method):
        if method == 'ROI':
            image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
            blimage = cv2.medianBlur(image, 15)
            circles = cv2.HoughCircles(blimage, cv2.HOUGH_GRADIENT, 1, 255, param1=100, param2=60, minRadius=0,
                                       maxRadius=0)
    
            if circles is not None:
                circles = np.uint16(np.around(circles))
                for i in circles[0, :]:
                    cv2.circle(image, (i[0], i[1]), i[2], (0, 255, 0), 6)
                    cv2.circle(image, (i[0], i[1]), 2, (0, 0, 255), 3)
            cv2.waitKey()
    
        else:
            print('method is wrong')
    
        return image
    

    界面
    enter image description here

    最佳答案

    更新:

    我添加了变量 border计算 x1,y1,x2,y2所以现在它带有边界线。图像显示不带 border 的旧代码的结果.

    如果你只有一个圈子(x,y,r)然后你可以用它来裁剪图像

    image = image[y-r:y+r, x-r:x+r]
    

    我在一些图像上测试它,圆圈比图像大,我不得不使用 int16而不是 unit16获取 -1而不是 65535对于 170-171 (y-r)。添加我必须使用 min() , 最大值() to get 0 instead -1`
    def ROI(self, image, method):
        if method == 'ROI':
            image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
            blimage = cv2.medianBlur(image, 15)
            circles = cv2.HoughCircles(blimage, cv2.HOUGH_GRADIENT, 1, 255, param1=100, param2=60, minRadius=0,
                                       maxRadius=0)
            if circles is not None:
                #print(circles)
    
                # need `int` instead of `uint` to correctly calculate `y-r` (to get `-1` instead of `65535`)
                circles = np.int16(np.around(circles)) 
    
                for x,y,r in circles[0, :]:
                    print('x, y, r:', x, y, r)
    
                    border = 6
    
                    cv2.circle(image, (x, y), r, (0, 255, 0), border)
                    cv2.circle(image, (x, y), 2, (0, 0, 255), 3)
    
                    height, width = image.shape
                    print('height, width:', height, width)
    
                    # calculate region to crop
                    x1 = max(x-r - border//2, 0)      # eventually  -(border//2+1)
                    x2 = min(x+r + border//2, width)  # eventually  +(border//2+1)
                    y1 = max(y-r - border//2, 0)      # eventually  -(border//2+1)
                    y2 = min(y+r + border//2, height) # eventually  +(border//2+1)
                    print('x1, x2:', x1, x2)
                    print('y1, y2:', y1, y2)
    
                    # crop image 
                    image = image[y1:y2,x1:x2]
                    print('height, width:', image.shape)
        else:
            print('method is wrong')
    
        return image
    

    对于更多圆圈,您必须首先计算用于所有圆圈的区域(获取 drom 所有圆圈最小值 x-ry-r 和最大值 x+ry+r )和下一个裁剪图像。

    enter image description here

    稍后我会尝试使用 alpha channel 来去除圆圈外的背景。

    用于测试的图像(如果其他人想测试代码)

    enter image description here

    编辑:我添加了创建带有白色圆圈的黑色图像以删除背景的代码。
    def ROI(self, image, method):
        if method == 'ROI':
            image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
            blimage = cv2.medianBlur(image, 15)
            circles = cv2.HoughCircles(blimage, cv2.HOUGH_GRADIENT, 1, 255, param1=100, param2=60, minRadius=0,
                                       maxRadius=0)
            if circles is not None:
                print(circles)
                circles = np.int16(np.around(circles)) # need int instead of uint to correctly calculate y-r (to get -1 instead of 65535)
                for x,y,r in circles[0, :]:
                    print('x, y, r:', x, y, r)
                    height, width = image.shape
                    print('height, width:', height, width)
    
                    border = 6
    
                    cv2.circle(image, (x, y), r, (0, 255, 0), border)
                    cv2.circle(image, (x, y), 2, (0, 0, 255), 3)
    
                    mask = np.zeros(image.shape, np.uint8) # black background
                    cv2.circle(mask, (x, y), r, (255), border)  # white mask for black border
                    cv2.circle(mask, (x, y), r, (255), -1) # white mask for (filled) circle
                    #image = cv2.bitwise_and(image, mask)  # image with black background
                    image = cv2.bitwise_or(image, ~mask)  # image with white background
    
                    x1 = max(x-r - border//2, 0)      # eventually  -(border//2+1)
                    x2 = min(x+r + border//2, width)  # eventually  +(border//2+1)
                    y1 = max(y-r - border//2, 0)      # eventually  -(border//2+1)
                    y2 = min(y+r + border//2, height) # eventually  +(border//2+1)
                    print('x1, x2:', x1, x2)
                    print('y1, y2:', y1, y2)
    
                    image = image[y1:y2,x1:x2]
                    print('height, width:', image.shape)
        else:
            print('method is wrong')
    
        return image
    

    enter image description here

    关于python - 如何仅提取图像的圆形 ROI 部分并通过在 Python OpenCV GUI 的 Tkinter 窗口中单击按钮来显示圆的半径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59477313/

    相关文章:

    python - 如何修复 PyXML?

    python - (范围(3),范围(3))值错误: too many values to unpack (expected 2)

    python - OpenCV - 将颜色掩模应用于彩色图像

    java - 如何在其他弹出窗口上显示弹出窗口?

    c++ - Win32 : How can i set the color of windows Title, 滚动条等?

    python - 带有 TensorFlow 的 Anaconda : No module named any_pb2

    python - 将原始数据分类到 csv 中。 Python

    opencv - 比较两个图像特定区域的直方图?打开简历

    python - 使用 Conda 在 Python 3.5 上安装 OpenCV

    git - merge 冲突解决