【问题标题】:Filling colour logically while drawing rectangle Tkinter绘制矩形Tkinter时逻辑填充颜色
【发布时间】:2020-04-03 07:49:46
【问题描述】:

使用 PIL 在画布中的图像上绘制矩形时。我希望根据画布中图像的像素颜色更改填充矩形。

我参考了其中一个交叉帖子(链接粘贴在下面)在 Tkinter 中创建带有鼠标事件的矩形。

create_rectangle 用鼠标事件指定的颜色填充矩形(例如:在本例中矩形用黑色填充)。有没有办法根据背景图像的现有像素颜色在逻辑上更改填充颜色?我的意思是,在绘制矩形时,我只需要将背景图像的白色像素变为红色,其余的变为不同的颜色。

Drawing rectangle using mouse events in Tkinter

[1]: https://i.stack.imgur.com/W41kX.jpg

def rec_on_button_press(self,event):
    self.start_x = event.x
    self.start_y = event.y
    self.rect=self.image_canvas.create_rectangle(self.x, self.y, 1, 1,fill=self.python_red)
def rec_on_move(self, event):
    curX, curY = (event.x, event.y)
    imagenp= np.array(image)
    if imagenp[curY,curX]==255:
        self.python_red="#EE204D"
    else:
        self.python_red=None
    self.image_canvas.coords(self.rect, self.start_x, self.start_y, curX, curY)

def rec_on_button_release(self, event):
    pass

【问题讨论】:

  • 听起来不太容易。你尝试了什么?
  • 我已经使用 numpy 将图像更改为数组并开始读取鼠标事件的每个像素。这个 if 语句实际上选择了初始鼠标位置并更改了填充颜色,但没有在鼠标拖动时读取所有像素?
  • 不太清楚你想做什么。你想制作一个选择框吗?如果没有,您能否使用 GIMP/Paint 等模拟图像
  • 你能用矩形内区域的预期输出创建一个图像吗?
  • 我认为你的想法不正确。根据你的想法(来自你的代码)。它最终会生成一个白色或红色填充的矩形,这取决于你按下的像素。跨度>

标签: python tkinter python-imaging-library drawrectangle


【解决方案1】:

原则: 裁剪您选择的图像,创建并显示它。

代码需要修改,完整代码示例(示例将255(白色)转换为0(黑色)):

import tkinter as tk # this is in python 3.4. For python 2.x import Tkinter
from PIL import Image, ImageTk
import numpy as np
import ctypes
ctypes.windll.shcore.SetProcessDpiAwareness(2) # for windows 10

class ExampleApp(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.x = self.y = 0
        self.canvas = tk.Canvas(self, width=512, height=512, cursor="cross")
        self.canvas.pack(side="top", fill="both", expand=True)
        self.canvas.bind("<ButtonPress-1>", self.on_button_press)
        self.canvas.bind("<B1-Motion>", self.on_move_press)
        self.canvas.bind("<ButtonRelease-1>", self.on_button_release)

        self.rect = None

        self.start_x = None
        self.start_y = None
        self.python_red = None

        self.im = Image.open(r'ImagePath').convert("L")
        self.move_imageID = None
        self.move_image = None
        self.tk_im = ImageTk.PhotoImage(self.im)
        self.canvas.create_image(0,0,anchor="nw",image=self.tk_im)



    def on_button_press(self, event):
        # save mouse drag start position
        self.start_x = event.x
        self.start_y = event.y
        self.rect = self.canvas.create_rectangle(self.x, self.y,  0, 0, outline="black")

    def on_move_press(self, event):
        self.canvas.delete(self.move_imageID)
        crop_image = self.im.crop((self.start_x,self.start_y,event.x,event.y))
        imageArray = np.array(crop_image)
        if imageArray.shape:
            for i in range(imageArray.shape[0]):
                for j in range(imageArray.shape[1]): # convert  the white pixel to black
                    if imageArray[i,j] == 255:
                        imageArray[i,j] = 0
            self.move_image = Image.fromarray(imageArray)
            self.move_image = ImageTk.PhotoImage(self.move_image)
            self.move_imageID = self.canvas.create_image(self.start_x,self.start_y,anchor="nw",image=self.move_image)
            self.canvas.coords(self.rect,self.start_x,self.start_y,event.x,event.y)
            self.canvas.lift(self.rect)

    def on_button_release(self, event):
        pass


if __name__ == "__main__":
    app = ExampleApp()
    app.mainloop()

现在:

选择区域:

【讨论】:

  • 感谢您的建议。两个观察: 1. 这个建议可以仅将当前矩形的白色像素转换为黑色。如果我尝试绘制太多矩形,之前处理/转换的像素会重置为白色,但这些矩形的轮廓仍然存在。 2. 当我处理 L 格式的图像时,它们的像素是 0 或 255。我很困惑,我该如何选择颜色(黄色或蓝色或绿色或橙色等)。非常感谢您的回复。
  • @zym 1.不,当你绘制第二个矩形时,第一个图片会消失。所以这就是为什么我说你需要修改它。2.你为什么要从一个灰度图像?你应该使用RGB模式而不是L模式。并且你还需要得到你想要的颜色的RGB值(比如the RGB value for green是rgb(0,128,0))。
  • @jizhihaoSAMA ,不幸的是,我从我的客户那里得到了一堆这样的图像。他们从成像系统生成这些图像,然后进行一些处理,最终形成 L 模式。
  • @zym 好吧,仔细想想。0-255只有256种颜色。RGB模式有256x256x256种颜色。为什么你会认为你可以直接在灰度图像中找到绿色或黄色等?
  • @jizhihaoSAMA,嗯,原因是:他们要求我根据我可以识别的特征给出颜色。此类图像将被其他人用于机器学习。
【解决方案2】:

原理:将image转换为numpy数组,使用opencv绘制矩形。处理后像素颜色转换回图像。

def rec_on_button_press(self,event):
        self.start_x = event.x
        self.start_y = event.y
        self.rect=self.image_canvas.create_rectangle(self.x, self.y, 1, 1,fill=self.python_red)
def rec_on_move(self, event):
        curX, curY = (event.x, event.y)
        cropimage=originalimage.crop((self.start_x,self.start_y,curX,curY))
        cropimagergb=cropimage.convert('RGB')
        cropimagergb.save('crop1.png')
        imagergbcv2=cv2.imread('crop1.png')
        if imagergbcv2.shape[:2]:
            for i in range(imagergbcv2.shape[0]):
                for j in range(imagergbcv2.shape[1]): 
                    color=imagergbcv2[i,j]
                    if (color[0]==255 and color[1]==255 and color[2]==255):
                        imagergbcv2[i,j]=(0,255,0)
        cv2.imwrite('crop2.png',imagergbcv2)
        croppedimage=cv2.imread('crop2.png')
        originalimage[self.start_y:self.start_y+croppedimage.shape[0],self.start_x:self.start_x+croppedimage.shape[1]]=croppedimage
        cv2.imwrite('originalpluscropped.png',originalimage)
    self.image_canvas.coords(self.rect, self.start_x, self.start_y, curX, curY)

def rec_on_button_release(self, event):
    pass
    self.image=Image.open('originalpluscropped.png')

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-09-08
    • 1970-01-01
    • 2013-02-01
    • 1970-01-01
    • 2012-07-03
    • 1970-01-01
    • 1970-01-01
    • 2014-01-13
    相关资源
    最近更新 更多