Python 如何使用tkinter比例修改图像?
我对Python和OpenCV相当陌生,所以如果我说/问的任何事情听起来可能不明智或不知情,我深表歉意。在我的数字图像处理课程中,我们以一种非常具体的方式学习了一些东西,因此,当我下面的代码正常工作时,我想极大地提高它的速度,但主要是它的UI。代码的主要目的是创建一个绿色屏幕图像的二值蒙版,然后将其应用于图像以将前景与背景分离。至于功能: keyer创建输入图像的阈值蒙版,具体取决于所需蒙版的类型(色差或色度) thresholdAdjust允许用户通过打开的CV UI操纵阈值滑块。它还实时更新图像(按下Enter键时),以反映原始蒙版如何根据选择的阈值进行更改。因为我对这些功能完全陌生,所以我看到的所有示例都使用了类似于跟踪器的函数。不过我不确定是否有必要 最后,keyMultiplier将在thresholdAdjust中生成的蒙版应用于输入图像,并显示分离的前景 (不必通读所有的键控器代码,因为它工作正常,但速度有点慢。我把所有代码都包括进来,以防万一。) 在第一段代码中,如果没有硬编码,我不知道如何确定要使用的图像和matteType 如果有人能帮我,我将不胜感激!我知道这是很多,我很乐意澄清任何困惑。一旦我知道如何使用滑块来实现这一点,我就应该能够将其应用于单选按钮。我想再次指出:Python 如何使用tkinter比例修改图像?,python,python-2.7,opencv,tkinter,Python,Python 2.7,Opencv,Tkinter,我对Python和OpenCV相当陌生,所以如果我说/问的任何事情听起来可能不明智或不知情,我深表歉意。在我的数字图像处理课程中,我们以一种非常具体的方式学习了一些东西,因此,当我下面的代码正常工作时,我想极大地提高它的速度,但主要是它的UI。代码的主要目的是创建一个绿色屏幕图像的二值蒙版,然后将其应用于图像以将前景与背景分离。至于功能: keyer创建输入图像的阈值蒙版,具体取决于所需蒙版的类型(色差或色度) thresholdAdjust允许用户通过打开的CV UI操纵阈值滑块。它还实时更新
- 使用阈值滑块更新我的键控器功能
- 使用OpenCV或Tkinter(以较容易的为准)实时更新蒙版
- 了解如何更改类中的输入图像和其他变量(如果适用)
谢谢大家! 好的,我花了几个小时讨论这个问题,我想我终于找到了一个解决方案(您需要在同一个目录下有一个
.png
文件名picture.png
,才能运行下面的程序):
从tkinter导入*
从PIL导入图像,ImageTk
类应用程序(框架):
定义初始(自我,主):
帧。\uuuu初始化(自,主)
self.frame1=帧(self)
self.frame2=帧(self)
self.original=Image.open('picture.png')
self.image=ImageTk.PhotoImage(self.original)
self.display=Canvas(self.frame1)
self.xscale=Scale(self.frame2,从0=1到=1000,方向=水平,命令=self.resize)
self.yscale=Scale(self.frame2,从0=1到=1000,方向=垂直,命令=self.resize)
self.display.pack(fill=BOTH,expand=1)
self.xscale.pack()
self.yscale.pack()
self.pack(填充=两者,扩展=1)
self.frame1.pack(fill=BOTH,expand=1)
self.frame2.pack()
self.bind(“,self.resize)
def调整大小(自身,*参数):
size=(self.xscale.get(),self.yscale.get())
resized=self.original.resize(大小、图像、别名)
self.image=ImageTk.PhotoImage(已调整大小)
self.display.delete(“IMG”)
self.display.create_image(self.display.winfo_width()/2,self.display.winfo_height()/2,anchor=CENTER,image=self.image,tags=“IMG”)
root=Tk()
app=app(根目录)
app.mainloop()
这样做的目的是创建一个canvas
和两个scale
s,每当一个刻度
s被更改时,它将调用def
resize
,它从画布上清除带有标记IMG
的项目,然后绘制一个新图像,其宽度等于xscale
的值,高度等于带有标记IMG
的yscale
。当您沿比例
s拖动滑块时,会产生实时大小更新的错觉
但是,我无法找到一种方法来将比例
的上限值限制为画布的宽度(以像素为单位),以防止用户将图像扩展到画布的边界之外
这可以类似地应用于允许您实时更新需要使用滑块值更新的图像的任何属性
import numpy as np
import cv2
def keyer(image, matteType, threshold1, threshold2, maxCount=255):
numberRows = image.shape[0]
numberColumns = image.shape[1]
if image.ndim > 2:
numberBands = image.shape[2]
else:
numberBands == 1
if numberBands != 3:
raise RuntimeError('Input image must be an RGB image.')
dataType = image.dtype
matte = np.zeros((numberRows, numberColumns, 1))
imageNorm = image / float(maxCount)
if matteType == 'colorDifference':
blue, green, red = cv2.split(imageNorm)
for row in range(numberRows):
for column in range(numberColumns):
pixel = green[row, column] - max(red[row, column], blue[row, column])
matte[row, column] = pixel
elif matteType == 'chromaKey':
imageYCbCr = cv2.cvtColor(image, cv2.COLOR_BGR2YCrCb)
imageYCbCrNorm = imageYCbCr / float(maxCount)
Y, Cr, Cb = cv2.split(imageYCbCrNorm)
CbScreen = Cb[0, 0]
CrScreen = Cr[0, 0]
for row in range(numberRows):
for column in range(numberColumns):
pixel = float(np.sqrt(((CbScreen - Cb[row, column])**2) + \
((CrScreen - Cr[row, column])**2)))
matte[row, column] = pixel
else:
raise RuntimeError('Please enter a valid "matteType".')
matte = np.clip(matte, 0.0, 1.0)
if matteType == 'colorDifference':
matte = 1.0 - matte
for row in range(numberRows):
for column in range(numberColumns):
if matte[row, column] < threshold1:
matte[row, column] = 0
elif matte[row, column] > threshold2:
matte[row, column] = 1
else:
matte[row, column] = ((matte[row, column] - threshold1) / \
(threshold2 - threshold1))
return (matte * float(maxCount)).astype(dataType)
def tracker(*arg):
pass
def thresholdAdjust(image, matteType, maxCount):
numberRows = image.shape[0]
numberColumns = image.shape[1]
if matteType == 'colorDifference':
matteName = '(Color Difference)'
else:
matteName = '(Chroma Key)'
windowName = 'Adjust Matte Parameters ' + matteName
threshold1TrackbarName = 'Clip Black'
threshold2TrackbarName = 'Clip White'
cv2.namedWindow(windowName)
cv2.createTrackbar(threshold1TrackbarName, windowName, 0, maxCount, tracker)
cv2.createTrackbar(threshold2TrackbarName, windowName, 0, maxCount, tracker)
cv2.setTrackbarPos(threshold2TrackbarName, windowName, maxCount)
while True:
threshold1 = (cv2.getTrackbarPos(threshold1TrackbarName, windowName) / \
float(maxCount))
threshold2 = (cv2.getTrackbarPos(threshold2TrackbarName, windowName) / \
float(maxCount))
window = keyer(image, matteType, threshold1, threshold2, maxCount)
cv2.imshow(windowName, window)
k = cv2.waitKey(0)
if k == 27:
break
cv2.destroyAllWindows()
return threshold1, threshold2
def keyMultiplier(image, matteType, maxCount):
dataType = image.dtype
threshold1, threshold2 = thresholdAdjust(image, matteType, maxCount)
matte = keyer(image, matteType, threshold1, threshold2, maxCount)
return ((cv2.GaussianBlur((matte / float(maxCount)), (3, 3), 0)[..., np.newaxis]) * \
image).astype(dataType)
if __name__ == '__main__':
import cv2
filename = 'C:/Users/Matt/Documents/circle_test.tif'
image = cv2.imread(filename)
difference = keyMultiplier(image, matteType='colorDifference', maxCount=255) # 163, 215
chroma = keyMultiplier(image, matteType='chromaKey', maxCount=255) # 25, 50
cv2.imshow('Original Image', image)
cv2.imshow('Color Difference', difference)
cv2.imshow('Chroma Key', chroma)
cv2.waitKey(0)
cv2.destroyAllWindows()
from Tkinter import *
class App():
def __init__(self):
self.root = Tk()
self.root.title('Adjust Matte Parameters')
self.clipBlack = Scale(self.root, from_=0, to=255, orient=HORIZONTAL, \
label='Clip Black', length=500)
self.clipBlack.bind("<ButtonRelease-1>", self.updateValue)
self.clipBlack.pack(anchor=CENTER)
self.clipWhite = Scale(self.root, from_=0, to=255, orient=HORIZONTAL, \
label='Clip White', length=500)
self.clipWhite.set(255)
self.clipWhite.bind("<ButtonRelease-1>", self.updateValue)
self.clipWhite.pack(anchor=CENTER)
self.root.mainloop()
def updateValue(self, event):
print 'Clip Black = ' + str(self.clipBlack.get())
print 'Clip White = ' + str(self.clipWhite.get())
app = App()
if __name__ == '__main__':
from tkinter import *
from PIL import Image, ImageTk
class App(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.frame1 = Frame(self)
self.frame2 = Frame(self)
self.original = Image.open('picture.png')
self.image = ImageTk.PhotoImage(self.original)
self.display = Canvas(self.frame1)
self.xscale = Scale(self.frame2, from_=1, to=1000, orient=HORIZONTAL, command=self.resize)
self.yscale = Scale(self.frame2, from_=1, to=1000, orient=VERTICAL, command=self.resize)
self.display.pack(fill=BOTH, expand=1)
self.xscale.pack()
self.yscale.pack()
self.pack(fill=BOTH, expand=1)
self.frame1.pack(fill=BOTH, expand=1)
self.frame2.pack()
self.bind("<Configure>", self.resize)
def resize(self, *args):
size = (self.xscale.get(), self.yscale.get())
resized = self.original.resize(size,Image.ANTIALIAS)
self.image = ImageTk.PhotoImage(resized)
self.display.delete("IMG")
self.display.create_image(self.display.winfo_width()/2, self.display.winfo_height()/2, anchor=CENTER, image=self.image, tags="IMG")
root = Tk()
app = App(root)
app.mainloop()