图片缩放不select正确区域

Picture zooming doesnt select the right area

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

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

对于缩放功能,用户应单击图片上的任意位置,它应剪切出光标单击处周围的 150x150 像素。准确地说,光标的点击应该标记我切出的矩形的中间。所以如果我点击 x=300 y=300 区域应该是 x=225 y=225 width=150 height=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 图片。 运行 程序。单击图像,它应该缩放。点击你的图像,你会看到缩放是错误的。

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

所以我找到了答案。但我也改变了一些逻辑。图片现在将以用户单击的位置为中心。这使用起来更直观。我只有 post 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()