使用wxPython从位图或wxImage获取像素信息

时间:2012-10-31 18:23:56

标签: colors bitmap wxpython pixel

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

以下是我的代码示例(我已将其缩短,但这是一个有效的示例):

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()正在读取的内容(因为调整大小的图像大小不同,我的代码不会读取所呈现的内容)。我意识到我可以获取像素的颜色信息,因为我正在查看wxImage而不是原始图像中的转换后的位图。通过将onMouseClick_img1事件调整为:

    def onMouseClick_img1(self, event):

        pos = event.GetPosition()

        print pos

我可以读取空的StaticBitMap上的任何点的位置,或者我转换为位图的已加载的已调整大小的图像。但是,我无法拉出所选像素的颜色信息。搜索后,我找到了this page

并尝试了两种方法,但最终都出现了错误。由于我想使用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))

但我收到此错误消息:

  

Traceback(最近一次调用最后一次):文件“/ Users / Documents / [user   name] /Eclipse_workspace/builder/src/GUI/Maybe.py“,第254行,in   onMouseClick_img1       img = wx.ImageFromBitmap(self.img_1)File“/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)TypeError:在方法'new_ImageFromBitmap'中,类型'wxBitmap的预期参数1   const&'

我认为我需要做的就是将位图重新调整后再将其转换为图像,然后从中提取像素信息,但我显然在某处做错了。任何帮助将不胜感激。这是我第一次尝试使用真正的GUI,我是wxPython的新手,所以如果你看到更普遍的错误,请随时告诉我。

1 个答案:

答案 0 :(得分: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中显示的图像。

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