通过改变画在图像上的线的宽度来获得多像素坐标?

2024-06-21 20:28:53 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图创建一些图像分析代码,我要求用户在图像上绘制一条直线或曲线,然后沿着这条线的像素的强度被记录下来。我希望能够改变线条的粗细,并沿宽度取像素的平均值,以给出沿线条每一点的平均强度,我不知道该怎么做。在视觉上,我可以改变绘图上线条的粗细,但它不影响所选像素的数量。我包含了下面的代码示例。在

import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
import sys

"""This class is a modification of the code created by Joerg Doepfert  2014 based on code posted by Daniel
Kornhauser. Which can be found at https://github.com/jdoepfert/roipoly.py /blob/master/roipoly.py """
class roipoly:
    def __init__(self, fig=[], ax=[], roicolor='b',thickness=2):
        if fig == []:
            fig = plt.gcf()
        if ax == []:
            ax = plt.gca()
        self.previous_point = []
        self.allxpoints = []
        self.allypoints = []
        self.start_point = []
        self.end_point = []
        self.line = None
        self.roicolor = roicolor
        self.thickness = thickness #I added this to change the thickness of the line on the plot
        self.fig = fig
        self.ax = ax
        self.__ID1 = self.fig.canvas.mpl_connect('motion_notify_event', self.__motion_notify_callback)
        self.__ID2 = self.fig.canvas.mpl_connect('button_press_event', self.__button_press_callback)
        if sys.flags.interactive:
            plt.show(block=False)
        else:
            plt.show()

    def displayIAL(self, **linekwargs):
        l = plt.Line2D(self.allxpoints,self.allypoints,color=self.roicolor,linewidth=self.thickness,**linekwargs)
        values=(self.allxpoints,self.allypoints)
        ax = plt.gca()
        ax.add_line(l)
        plt.draw()
        return values

    def __motion_notify_callback(self, event):
        if event.inaxes:
            ax = event.inaxes
            x, y = event.xdata, event.ydata
            if (event.button == None or event.button == 1) and self.line != None: # Move line around
                self.line.set_data([self.previous_point[0], x],[self.previous_point[1], y])
                self.fig.canvas.draw()

    def __button_press_callback(self, event):
        if event.inaxes:
            x, y = event.xdata, event.ydata
            ax = event.inaxes
            if event.button == 1 and event.dblclick == False:  # If you press the left button, single click
                if self.line == None: # if there is no line, create a line
                    self.line = plt.Line2D([x, x],[y, y],marker='o',color=self.roicolor, linewidth=self.thickness)
                    self.start_point = [x,y]
                    self.previous_point =  self.start_point
                    self.allxpoints=[x]
                    self.allypoints=[y]                        
                    ax.add_line(self.line)
                    self.fig.canvas.draw()
                    # add a segment
                else: # if there is a line, create a segment
                    self.line = plt.Line2D([self.previous_point[0], x],[self.previous_point[1], y],marker = 'o',color=self.roicolor,linewidth=self.thickness)
                    self.previous_point = [x,y]
                    self.allxpoints.append(x)
                    self.allypoints.append(y)                                                    
                    event.inaxes.add_line(self.line)
                    self.fig.canvas.draw()
            elif ((event.button == 1 and event.dblclick==True) or (event.button == 3 and event.dblclick==False)) and  self.line != None: # close the loop and disconnect
                self.fig.canvas.mpl_disconnect(self.__ID1) #joerg
                self.fig.canvas.mpl_disconnect(self.__ID2) #joerg  
                self.line.set_data([self.previous_point[0],self.start_point[0]],[self.previous_point[1],self.start_point[1]])
                ax.add_line(self.line)
                self.fig.canvas.draw()
                self.line = None        
                if sys.flags.interactive:
                    pass
                else:
                    #figure has to be closed so that code can continue
                    plt.close(self.fig)

#This function returns a list of lists with the x coordinates and the y coordinates being separated into their own lists
def getIAL(img, width):
    im = np.array(img)
    plt.imshow(im, interpolation='nearest', cmap="Greys")
    plt.title("left click: line segment, right click: close region")
    ROIl = roipoly(roicolor='g',thickness=width)
    plt.imshow(im, interpolation='nearest', cmap="Greys")
    myIAL=ROIl.displayIAL()
    plt.clf()
    return myIAL  

#This function takes the intensity of each x,y coordinate and then plots     the intensities vs. distance along the line which was drawn         
def IAL_Plot(IAL, image):
    xvalues=IAL[0]
    yvalues=IAL[1]
    imarray=np.array(image)
    intensityvalues=[]
    for i in range(len(xvalues)):
        x=int(xvalues[i])
        y=int(yvalues[i])
        intensityvalue=imarray[y,x]
        intensityvalues.append(intensityvalue)
    def display(Intensity):
        plt.plot(Intensity)
        plt.xlabel('Distance', fontsize=16)
        plt.ylabel('Intensity',fontsize=16)
        plt.show()
    display(intensityvalues)


#Generate a greyscale plot
array=np.linspace(0,1,256*256)
mat=np.reshape(array,(256,256))
img=Image.fromarray(np.uint8(mat*255),'L')

myIAL=getIAL(img, 5) #get the coordinates of a line drawn on the image
plot=IAL_Plot(myIAL,img) #get the intensity at each coordinate point

我认为有一种Python式的方法可以做到这一点,或者至少有一种数学的方法,但到目前为止我还是一片空白。如有任何帮助/建议,将不胜感激。在


Tags: andtheselfeventifdeflinefig