【问题标题】:Picture zooming doesnt select the right area图片缩放没有选择正确的区域
【发布时间】:2020-04-29 09:30:20
【问题描述】:

我有一个显示图像的应用程序。由于人们需要从图像中读取一些信息,因此我实现了缩放功能。

我将图片小部件设置为 600x600。为了保留纵横比,我然后缩放图片并将其绘制到小部件。这真的很好用。

对于缩放功能,用户应该点击图片上的任意位置,它应该在光标点击的地方剪掉 150x150 像素。准确地说,光标的点击应该标记我切出的矩形的中间。因此,如果我单击 x=300 y=300,则该区域应为 x=225 y=225 宽度=150 高度=150。

要存档,我将用户单击的坐标缩放回原始图像分辨率,剪切子图像并将其缩小。剪掉我的程序中已经加载的缩放图像会产生更差的质量。

错误很简单。切出的区域并不完全是我想要切出的区域。有时它在最左边。有时到最右边。有时到高有时到低……我看不出问题出在哪里。

我编写了一个只包含所需功能的准系统原型。输入 jpeg 图片的路径后,您应该能够运行它。

# -*- coding: utf-8 -*-
"""
Created on Sun Jan 12 12:22:25 2020

@author: Paddy
"""

import wx


class ImageTest(wx.App):
    def __init__(self, redirect=False, filename=None):
        wx.App.__init__(self, redirect, filename)

        self.frame = wx.Frame(None, title='Radsteuer Eintreiber')   

        self.panelleft = wx.Panel(self.frame)
        self.picturepresent=False
        self.index=0
        self.PhotoMaxSize = 600
        self.zoomed=False
        #Change path here
        self.imagepath='F:\Geolocation\Test\IMG_20191113_174257.jpg'
        self.createUI()
        self.frame.Centre()
        self.frame.Show()
        self.frame.Raise()
        self.onView()
    #Creates UI Elements on Initiation    
    def createUI(self):
        #instructions = 'Bild'
        img = wx.Image(self.PhotoMaxSize,self.PhotoMaxSize,clear=True)
        self.imageCtrl = wx.StaticBitmap(self.panelleft, wx.ID_ANY, 
                                         wx.Bitmap(img),size=(self.PhotoMaxSize,self.PhotoMaxSize))
        self.mainSizer = wx.BoxSizer(wx.VERTICAL)        

        self.imageCtrl.Bind(wx.EVT_LEFT_UP, self.onImageClick)     


        self.mainSizer.Add(self.imageCtrl, 0, wx.ALL|wx.ALIGN_CENTER, 5)

        self.panelleft.SetSizer(self.mainSizer)
        self.mainSizer.Fit(self.frame)

        self.panelleft.Layout()




    def onImageClick(self,event):
        if self.zoomed:
            self.onView()
            self.zoomed=False
        else :
            #Determin position of mouse
            ctrl_pos = event.GetPosition()
            print(ctrl_pos)
            picturecutof=self.PhotoMaxSize/4
            if ctrl_pos[0]-((self.PhotoMaxSize-self.NewW)/2)>0:
                xpos=ctrl_pos[0]-((self.PhotoMaxSize-self.NewW)/2)
            else:
                xpos=0                
            if ctrl_pos[0]+picturecutof>self.NewW:
                xpos=self.NewW-picturecutof


            if ctrl_pos[1]-((self.PhotoMaxSize-self.NewW)/2)>0:
                ypos=ctrl_pos[1]-((self.PhotoMaxSize-self.NewW)/2)
            else:
                ypos=0                
            if ctrl_pos[1]+picturecutof>self.NewH:
                ypos=self.NewH-picturecutof


            xpos=xpos*self.W/self.NewW    
            ypos=ypos*self.H/self.NewH
            picturecutofx=picturecutof*self.W/self.NewW
            picturecutofy=picturecutof*self.H/self.NewH

            rectangle=wx.Rect(xpos,ypos,picturecutofx,picturecutofy)
            self.img = wx.Image(self.imagepath, wx.BITMAP_TYPE_ANY)
            self.img=self.img.GetSubImage(rectangle)

            self.img=self.img.Scale(600,600,wx.IMAGE_QUALITY_BICUBIC)
            self.imageCtrl.SetBitmap(wx.Bitmap(self.img))
            self.imageCtrl.Fit()
            self.panelleft.Refresh()
            self.zoomed=True

    def onView(self,event=None):


        self.img = wx.Image(self.imagepath, wx.BITMAP_TYPE_ANY)
        # scale the image, preserving the aspect ratio
        self.W = self.img.GetWidth()
        self.H = self.img.GetHeight()

        if self.W > self.H:
            self.NewW = self.PhotoMaxSize
            self.NewH = self.PhotoMaxSize * self.H / self.W
        else:
            self.NewH = self.PhotoMaxSize 
            self.NewW = self.PhotoMaxSize * self.W / self.H

        self.img = self.img.Scale(self.NewW,self.NewH,wx.IMAGE_QUALITY_BICUBIC)        
        self.imageCtrl.SetBitmap(wx.Bitmap(self.img))
        self.imageCtrl.Fit()
        self.panelleft.Refresh()

if __name__ == '__main__':

    app = ImageTest()
    app.MainLoop()   

代码中可能发生了一些不完全有意义的奇怪事情。大部分是因为普通程序要大得多,并且我在原型中删除了许多与缩放无关的功能。很可能是我做错了缩放。但我没有想法。

此原型的功能很简单:将路径替换为您选择的 jpge 图像。运行程序。单击图像,它应该会缩放。单击您的图像,您会看到缩放错误。

就是这样。谢谢你的帮助。

【问题讨论】:

    标签: python-3.x wxpython wxwidgets scaling


    【解决方案1】:

    所以我找到了答案。但我也改变了一些逻辑。图片现在将以用户单击的位置为中心。这使用起来更加直观。我只发布 onImageClick 函数。如果您想使用整个东西,请随时在问题的原始代码中替换它。

    def onImageClick(self,event):
        if self.zoomed:
            self.onView()
            self.zoomed=False
        else :
            #Determin position of mouse
            ctrl_pos = event.GetPosition()
    
            #Set magnification.
            scalingfactor=4       
    
            #Set Picture size for rectangle            
            picturecutof=self.PhotoMaxSize/scalingfactor
    
            ##Find coordinates by adjusting for picture position
            xpos=ctrl_pos[0]-((self.PhotoMaxSize-self.NewW)/2) 
            ypos=ctrl_pos[1]-((self.PhotoMaxSize-self.NewH)/2)
    
            #if position is out of range adjust
            if xpos>self.NewW:
                xpos=self.NewW
            if xpos<0:
                xpos=0
    
            if ypos>self.NewH:
                ypos=self.NewH
            if ypos<0:
                ypos=0
    
    
            #scale rectangle area to size of the unscaled image
            picturecutofx=picturecutof*self.W/self.NewW            
            picturecutofy=picturecutof*self.H/self.NewH
    
    
    
            #scale coordinates to unscaled image
            xpos=xpos*self.W/self.NewW
            ypos=ypos*self.H/self.NewH
    
            #centeres image onto the coordinates where they were clicked
            xpos=xpos-((ctrl_pos[0]*self.W/self.NewW)/scalingfactor)
            ypos=ypos-((ctrl_pos[1]*self.H/self.NewH)/scalingfactor)
    
    
            #if position is out of range adjust
            if xpos>self.W-picturecutofx:
                xpos=self.W-picturecutofx-5
            if xpos<0:
                xpos=0
    
            if ypos>self.H-picturecutofy:
                ypos=self.H-picturecutofy-5
            if ypos<0:
                ypos=0
    
            #create rectangle to cut from original image
            rectangle=wx.Rect(xpos,ypos,picturecutofx,picturecutofy)
            #load original image again
            self.img = wx.Image(self.imagepath, wx.BITMAP_TYPE_ANY)
            #get subimage 
            self.img=self.img.GetSubImage(rectangle)
    
            #scale subimage to picture area
            self.img=self.img.Scale(self.PhotoMaxSize,self.PhotoMaxSize,wx.IMAGE_QUALITY_BICUBIC)
            self.imageCtrl.SetBitmap(wx.Bitmap(self.img))
            self.imageCtrl.Fit()
            self.panelleft.Refresh()
            self.zoomed=True
    
        event.Skip()
    

    【讨论】:

      猜你喜欢
      • 2011-06-18
      • 2015-12-21
      • 1970-01-01
      • 2013-04-12
      • 1970-01-01
      • 1970-01-01
      • 2012-11-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多