Skip to main content
 首页 » 编程设计

python之查找轮廓和边界以获取图像内部的点 OpenCV Python

2025年05月04日21mayingbao

我有一个代码可以在图像中绘制对象的轮廓,然后在它们周围绘制一个矩形。我需要找到形状中最宽的直径(两点)女巫是水平直线现在我需要找到对象边界内的点(像素坐标)。

这是我的代码:

class App: 
    def __init__(self, window, window_title, image_path="ex.jpg"): 
        self.window = window 
        self.window.title(window_title) 
 
        # Load an image using OpenCV 
        self.cv_img = cv2.cvtColor(cv2.imread(image_path), cv2.COLOR_BGR2RGB) 
 
        # Get the image dimensions (OpenCV stores image data as NumPy ndarray) 
        self.height, self.width, no_channels = self.cv_img.shape 
 
        # Create a canvas that can fit the above image 
        self.canvas = tkinter.Canvas(window, width = self.width, height = self.height) 
        self.canvas.pack() 
 
        # Use PIL (Pillow) to convert the NumPy ndarray to a PhotoImage 
        self.photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(self.cv_img)) 
 
        # Add a PhotoImage to the Canvas 
        self.canvas.create_image(0, 0, image=self.photo, anchor=tkinter.NW) 
 
        # Button that lets the user blur the image 
        self.btn_blur=tkinter.Button(window, text="Blur", width=25, command=self.blur_image) 
        self.btn_blur.pack(anchor=tkinter.CENTER, expand=True) 
 
        # Button that lets the user edeged the image 
        self.btn_blur=tkinter.Button(window, text="edged", width=25, command=self.edged_image) 
        self.btn_blur.pack(anchor=tkinter.CENTER, expand=True) 
 
        # Button that lets the user edeged the image 
        self.btn_blur=tkinter.Button(window, text="draw box", width=25, command=self.draw_box) 
        self.btn_blur.pack(anchor=tkinter.CENTER, expand=True) 
 
        self.window.mainloop() 
 
    # Callback for the "Blur" button 
    def blur_image(self): 
        self.cv_img = cv2.blur(self.cv_img, (3, 3)) 
        self.photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(self.cv_img)) 
        self.canvas.create_image(0, 0, image=self.photo, anchor=tkinter.NW) 
 
    # Callback for the "edged" button 
    def edged_image(self): 
        #edeged image 
        self.cv_img=cv2.Canny(self.cv_img,50,180) 
        self.cv_img = cv2.dilate(self.cv_img, None, iterations=1) 
        self.cv_img = cv2.erode(self.cv_img, None, iterations=1) 
        self.photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(self.cv_img)) 
        self.canvas.create_image(0, 0, image=self.photo, anchor=tkinter.NW) 
 
    # Callback for the "draw contours" button 
    def draw_box(self):         
        #draw contour 
        cnts = cv2.findContours(self.cv_img.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) 
        cnts = cnts[0] if imutils.is_cv2() else cnts[1] 
        #draw box 
        for c in cnts: 
            self.cv_img = cv2.drawContours(self.cv_img, [c], 0, (0,255,0), 3) 
            x,y,w,h = cv2.boundingRect(c) 
            self.cv_img = cv2.rectangle(self.cv_img,(x,y),(x+w,y+h),(0,255,0),2) 
 
#Create a window and pass it to the Application object 
App(tkinter.Tk(), "morteza app") 

请您参考如下方法:

您可以尝试找到极值点(在您的情况下为左、右和上)。然后,您可以使用计算两点之间距离的公式 d=sqrt((x2-x1)^2 + (y2-y1)^2) 来计算从极左到极右的距离。如果您愿意,您甚至可以使用相同的原理找到线的中心并计算线的中心与最高点之间的距离。这是一个示例代码:

import numpy as np 
import cv2 
import imutils 
 
img = cv2.imread('bulb.png') 
 
 
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 
ret, thresh = cv2.threshold(gray, 240, 255, cv2.THRESH_BINARY) 
cv2.bitwise_not(thresh, thresh) 
 
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, 
                cv2.CHAIN_APPROX_SIMPLE) 
cnts = cnts[0] 
c = max(cnts, key=cv2.contourArea) 
 
left = tuple(c[c[:, :, 0].argmin()][0]) 
right = tuple(c[c[:, :, 0].argmax()][0]) 
 
distance = np.sqrt( (right[0] - left[0])**2 + (right[1] - left[1])**2 ) 
 
x,y,w,h = cv2.boundingRect(c) 
 
centx = np.sqrt( ((right[0] + left[0])**2)/4) 
centy = np.sqrt( ((right[1] + left[1])**2)/4 ) 
print(centx, centy) 
 
font = cv2.FONT_HERSHEY_SIMPLEX 
cv2.circle(img, left, 5, (0, 0, 255), -1) 
cv2.circle(img, right, 5, (0, 0, 255), -1) 
cv2.circle(img, (int(centx), int(centy)), 5, (0, 0, 255), -1) 
cv2.line(img, left, right, (255,0,0), 2) 
cv2.drawContours(img, [c], -1, (0,255,0), 2) 
cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2) 
cv2.putText(img,'Distance: '+str(distance),(10,30), font, 1, (0,0,0),2, cv2.LINE_AA) 
cv2.imshow('img', img) 
cv2.imwrite('bulbresult.png', img) 

结果: