Логическая заливка цвета при рисовании прямоугольника Tkinter

При использовании PIL нарисуйте прямоугольники на изображении на холсте. Я хочу изменить прямоугольник заливки в зависимости от цвета пикселей моего изображения на холсте.

Я сослался на один из перекрестных сообщений (ссылка вставлена ​​ниже) для создания прямоугольников с событиями мыши в Tkinter.

create_rectangle заполняет прямоугольник цветом, заданным событиями мыши (пример: в этом примере прямоугольник залит черным). Есть ли способ логически изменить цвет заливки в зависимости от существующего цвета пикселей фонового изображения? Я имею в виду, что при рисовании прямоугольника мне нужно, чтобы только белые пиксели фонового изображения стали красными, а остальные - другим цветом.

Рисование прямоугольника с использованием событий мыши в Tkinter

введите описание изображения здесь

https://i.stack.imgur.com/0K5t1.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

person zym    schedule 03.04.2020    source источник
comment
Звучит непросто. Что вы пробовали?   -  person jizhihaoSAMA    schedule 03.04.2020
comment
Я использовал numpy, чтобы преобразовать изображение в массив, и начал читать каждый пиксель события мыши. Это, если оператор действительно выбирает начальную позицию мыши и меняет цвет заливки, но не считывает все пиксели при перетаскивании мыши?   -  person zym    schedule 03.04.2020
comment
Не очень понятно, что ты хочешь делать. Вы хотите сделать поле выбора? Если нет, не могли бы вы создать макет изображения с помощью GIMP / Paint и т. Д.   -  person Edwin Clement    schedule 03.04.2020
comment
Найдите перекрестную стойку, которую я использовал для рисования прямоугольников на моем существующем холсте. stackoverflow.com/q/24135170/6864167   -  person zym    schedule 03.04.2020
comment
Можете ли вы создать изображение с ожидаемым результатом для области внутри прямоугольника?   -  person acw1668    schedule 03.04.2020
comment
Я думаю, ваша идея неверна. Согласно вашей идее (из вашего кода), он, наконец, сгенерирует заливку прямоугольника белым или красным, в зависимости от пикселя, на который вы нажали.   -  person jizhihaoSAMA    schedule 03.04.2020
comment
Вы можете использовать create_image для покрытия изображения вместо использования только create_rectangle.   -  person jizhihaoSAMA    schedule 03.04.2020
comment
Кстати, если ваше изображение имеет формат RGB, вы должны использовать imagenp[curY,curX].all([255,255,255]) вместо imagenp[curY,curX]==255.   -  person jizhihaoSAMA    schedule 03.04.2020
comment
Мое изображение имеет режим L, в отличие от RGB. И все мои изображения имеют значение 0 или 255 в пикселях.   -  person zym    schedule 03.04.2020


Ответы (2)


Принцип: обрежьте выбранное изображение, создайте его и покажите.

Код необходимо изменить, пример полного кода (пример - преобразование 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()

Теперь:

введите описание изображения здесь

Выберите область:

введите описание изображения здесь

person jizhihaoSAMA    schedule 03.04.2020
comment
Спасибо за ваш совет. Два наблюдения: 1. Это предложение может преобразовывать белые пиксели в черные только для текущего прямоугольника. Если я попытаюсь нарисовать слишком много прямоугольников, ранее обработанные / преобразованные пиксели сбрасываются до белого цвета, но контур этих прямоугольников все еще на месте. 2. Поскольку я имею дело с изображениями формата L, их пиксели либо 0, либо 255. Я не понимаю, как я могу выбрать цвет (желтый или синий, зеленый или оранжевый и т. Д.). Тем не менее, очень признателен за ваш ответ. - person zym; 03.04.2020
comment
@zym 1. Нет, когда вы рисуете второй прямоугольник, первое изображение исчезнет. Поэтому я говорю, что вам нужно его изменить. 2. Почему вы хотите выбирать цвет из изображения в градациях серого? Вам следует использовать режим RGB вместо режима L. И вам также необходимо получить значение RGB того цвета, который вы хотите (например, значение RGB для зеленого равно rgb (0,128,0)). - person jizhihaoSAMA; 03.04.2020
comment
@ jizhihaoSAMA, К сожалению, я получаю много таких изображений от своего покупателя. Они генерируют эти изображения из системы обработки изображений и после некоторой обработки, которая в конечном итоге привела к L-режиму. - person zym; 06.04.2020
comment
@zym Хорошо подумайте: 0-255 имеет только 256 видов цветов. Режим RGB имеет 256x256x256 видов цветов. Почему вы думаете, что вы можете найти зеленый или желтый и т. д. непосредственно в изображении в градациях серого? - person jizhihaoSAMA; 06.04.2020
comment
@ jizhihaoSAMA, Ну, причина в том, что они просят меня указать цвет на основе той особенности, которую я смог идентифицировать в нем. Такие изображения будут использоваться для машинного обучения кем-то другим. - person zym; 06.04.2020
comment
Machine Learning, это должен быть другой вопрос. Я скажу, что вы спросили, как Filling colour logically while drawing rectangle Tkinter, а не _3 _. (Это тоже большая проблема.) Я сделал то, что делаю. - person jizhihaoSAMA; 06.04.2020
comment
Наконец-то я это сделал. Пожалуйста, обратитесь к моему решению, размещенному здесь. Спасибо @jizhihaoSAMA - person zym; 09.04.2020

Принцип: конвертируйте изображение в массив 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')
person zym    schedule 09.04.2020