1

我有一个关于从位图中获取单个像素颜色信息的问题。我搜索了这些论坛以及演示和教程,虽然我相信我在理论上了解我需要做的事情,但实际上我无法做到。

这是我的代码示例(我已经缩短了它,但这是一个工作示例):

import os, sys
import wx
import wx.lib.plot as plot
import Image

class MyFrame(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(500, 500))

        HolderPanel = wx.Panel(self, wx.ID_ANY)

        panel2 = MyPanel_2(HolderPanel, wx.ID_ANY)

        framesizer = wx.BoxSizer(wx.HORIZONTAL)
        framesizer.Add(panel2, 1, wx.EXPAND | wx.BOTTOM | wx.TOP | wx.RIGHT, 2)

        HolderSizer = wx.BoxSizer(wx.VERTICAL)
        HolderSizer.Add(framesizer, 1, wx.EXPAND)

        HolderPanel.SetSizer(HolderSizer)
        self.Show()


class MyPanel_2(wx.Panel):

    def __init__(self, parent, id):
        wx.Panel.__init__(self, parent, id, style=wx.SIMPLE_BORDER)
        self.SetBackgroundColour('grey')


        # Create main image holder
        self.img_1 = wx.EmptyImage(300,300)        
        self.imageCtrl_1 = wx.StaticBitmap(self, wx.ID_ANY, wx.BitmapFromImage(self.img_1)) # Starting with an EmptyBitmap, the real one will get put there by the call onView
        self.PhotoMaxSize_1 = (300)
        self.imageCtrl_1.Bind(wx.EVT_LEFT_DOWN, self.onMouseClick_img1)

        # Create the browse button
        brwsBtn = wx.Button(self, wx.ID_ANY, 'Browse', (10, 10))
        brwsBtn.Bind(wx.EVT_BUTTON, self.onBrowse)

        # Set up the text box
        self.photoTxt = wx.TextCtrl(self, size=(200,-1))

        # Create the sizers
        vsizer1 = wx.BoxSizer(wx.VERTICAL)
        hsizer3 = wx.BoxSizer(wx.HORIZONTAL)
        vsizer_MAIN = wx.BoxSizer(wx.VERTICAL)

        # -----------------------------------------------------------------------------------------------------------
        vsizer1.Add(self.imageCtrl_1, proportion = 0, flag= wx.ALIGN_CENTRE | wx.ALL, border=10)

        # -----------------------------------------------------------------------------------------------------------
        hsizer3.Add(brwsBtn, proportion = 0, flag = wx.ALIGN_CENTRE_VERTICAL | wx.LEFT | wx.RIGHT, border=10)
        hsizer3.Add(self.photoTxt, proportion = 1, flag = wx.ALIGN_CENTRE_VERTICAL | wx.LEFT | wx.RIGHT, border = 10)

        # -----------------------------------------------------------------------------------------------------------
        vsizer_MAIN.Add(vsizer1, proportion = 1, flag = wx.EXPAND)
        vsizer_MAIN.Add(hsizer3, proportion = 1, flag = wx.EXPAND)

        # -----------------------------------------------------------------------------------------------------------
        self.SetSizer(vsizer_MAIN)

    def onBrowse(self, event):
        """ 
        Browse for file
        """
        wildcard = "pictures (*.jpg, *.jpeg, *.png)|*.jpg;*.jpeg;*.png"
        dialog = wx.FileDialog(None, "Choose a file", wildcard=wildcard, style=wx.OPEN)

        if dialog.ShowModal() == wx.ID_OK:
            self.photoTxt.SetValue(dialog.GetPath())
        dialog.Destroy() 
        self.onView()

    def onView(self):

        self.filepath = self.photoTxt.GetValue()

        self.img_1 = wx.Image(self.filepath, wx.BITMAP_TYPE_ANY)
        # scale the image, preserving the aspect ratio
        W = self.img_1.GetWidth()
        H = self.img_1.GetHeight()
        if W > H:
            NewW = self.PhotoMaxSize_1
            NewH = self.PhotoMaxSize_1 * H / W
        else:
            NewH = self.PhotoMaxSize_1
            NewW = self.PhotoMaxSize_1 * W / H
        self.img_1 = self.img_1.Scale(NewW,NewH)

        self.imageCtrl_1.SetBitmap(wx.BitmapFromImage(self.img_1)) # Converts the scaled image to a wx.Bitmap and put it on the wx.StaticBitmap
        self.Refresh()

    def onMouseClick_img1(self, event):

        im = Image.open(self.filepath)
        pos = event.GetPosition()
        pix = im.load()
        print pix[pos.x, pos.y]

app = wx.App()
MyFrame(None, -1, 'Current Build')
app.MainLoop()

这允许我浏览并导入图像,调整图像大小,然后选择单个像素以访问其颜色信息。但是,此代码存在一个问题:颜色信息与实际图像不匹配(在某些情况下,存在与超出图像范围有关的错误)。我回去检查这个并意识到

        im = Image.open(self.filepath)

正在引用图像的实际路径,这就是event.GetPosition()正在读取的内容(因为调整大小的图像大小不同,我的代码没有读取呈现的内容)。我意识到我可以获取像素的颜色信息,因为我正在查看的是 awxImage而不是原始图像的转换位图。通过将onMouseClick_img1事件调整为:

    def onMouseClick_img1(self, event):

        pos = event.GetPosition()

        print pos

我可以读取空 StaticBitMap 或已加载、已调整大小且已转换为位图的图像上任何点的位置。但是,我无法提取所选像素的颜色信息。经过搜索,我找到了这个页面

并尝试了两种方法,但最终都出现了错误。由于我想使用该wx.Image方法,所以我尝试了这个:

    def onMouseClick_img1(self, event):

        img = wx.ImageFromBitmap(self.img_1)

        pos = event.GetPosition()
        print (img.GetRed(pos), img.GetGreen(pos), img.GetBlue(pos))

但我收到此错误消息:

回溯(最近一次调用最后):文件“/Users/Documents/[用户名]/Eclipse_workspace/builder/src/GUI/Maybe.py”,第 254 行,onMouseClick_img1 img = wx.ImageFromBitmap(self.img_1) 文件“ /usr/local/Cellar/python/2.7.3/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/wx/_core.py”,第 3750 行,在 ImageFromBitmap val = core .new_ImageFromBitmap (*args, **kwargs) 类型错误:在方法“new_ImageFromBitmap”中,预期参数 1 类型为“wxBitmap const &”

我认为我需要做的就是在调整位图大小后将位图转换回图像,然后从中提取像素信息,但我显然在某处做错了什么。任何帮助将不胜感激。这是我第一次尝试真正的 GUI,而且我是新手wxPython,所以如果您发现更一般的错误,请随时告诉我。

4

1 回答 1

1

所以,我找到了一种方法来完成这项工作。也许我一开始并没有完全理解我需要做什么(也许我在这里仍然缺少关键想法),但我所做的工作有效。可能是我得到这个工作的方式是丑陋或低效的......但它有效。我有没有提到我认为这行得通?

我没有尝试从显示的位图中提取任何信息,或者将位图转换为另一种格式并显示,而是在 StaticBitmap 中显示调整大小的图像并使用另一种方法来提取像素信息:

    def onView(self):
    """ 
    This is pulling in the image and resizing it, maintaining its original ratio; if the image is square, this is fine as long as the image boxes are square; the ratios
    are getting messed up depending on the size of the picture; I would imagine that the images we're going to be importing are going to be pretty uniform.
    """        

    # Code imports and resizes the image
    self.filepath = self.photoTxt.GetValue()

    self.img_1 = wx.Image(self.filepath, wx.BITMAP_TYPE_ANY)
    # scale the image, preserving the aspect ratio
    W = self.img_1.GetWidth()
    H = self.img_1.GetHeight()
    if W > H:
        NewW = self.PhotoMaxSize_1
        NewH = self.PhotoMaxSize_1 * H / W
    else:
        NewH = self.PhotoMaxSize_1
        NewW = self.PhotoMaxSize_1 * W / H
    self.img_1 = self.img_1.Scale(NewW,NewH)

    self.imageCtrl_1.SetBitmap(wx.BitmapFromImage(self.img_1)) # Converts the scaled image to a wx.Bitmap and put it on the wx.StaticBitmap
    self.Refresh()

    # Code creates an image using wxImage to pull pixel information from
    self.img_1_IMAGE = Image.open(self.filepath)
    self.img_1_IMAGE_r = self.img_1_IMAGE.resize((NewW, NewH))

def onMouseClick_img1(self, event):

    im = self.img_1_IMAGE_r
    pos = event.GetPosition()
    pix = im.load()
    print pix[pos.x, pos.y]

关键的区别似乎是(至少对我而言)我没有将此图像转换为位图并将其分配给我的 StaticBitmap。这允许我在调用 onMouseClick_img1 时访问调整大小图像的像素信息。由于我对每个图像使用相同的调整大小参数,因此尺寸应该匹配(而且他们似乎这样做),允许我在从调整大小的图像中提取像素信息时看到显示的 StaticBitmap 中的图像。

如果有人对此有任何意见或疑虑,请随时告诉我。我只是想发布我发现的内容,以防其他人遇到类似问题。

于 2013-07-03T19:01:08.430 回答