2012-10-31 18 views
1

我有一个关于从位图获取单个像素的颜色信息的问题。我搜索了这些论坛,以及演示和教程,虽然我相信我理解我理论上需要做什么,但我无法真正做到。位图或wxImage使用wxPython的像素信息

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

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 (most recent call last): File "/Users/Documents/[user name]/Eclipse_workspace/builder/src/GUI/Maybe.py", line 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", line 3750, in ImageFromBitmap val = core.new_ImageFromBitmap(*args, **kwargs) TypeError: in method 'new_ImageFromBitmap', expected argument 1 of type 'wxBitmap const &'

我认为所有我需要做的是转换位图回一旦我调整了图像的大小,然后从中提取像素信息,但我显然在某处做了不正确的事情。任何帮助将不胜感激。这是我第一次尝试一个真正的GUI,我是wxPython的新手,所以如果你看到一些更一般的错误,请随时告诉我。

+1

如果您可以将解决方案内容解决出来,并通过解决方案创建您自己的答案,那将更具可读性。因为这个问题现在这么长,所以很难解决这个问题。 – demongolem

+0

我完全同意。当我第一次发布这篇文章时,我认为我需要一定的评分才能回答我自己的问题(因为这是我的第一篇文章,所以我没有这个问题)。总之,情况并非如此,所以我修正了它。 – user1759566

回答

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中显示的图像。

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

相关问题