Найти - Пользователи
Полная версия: Добаление интерфейса к скрипту используя PyQt
Начало » GUI » Добаление интерфейса к скрипту используя PyQt
1
mgmn
Ребята привет, нужна помощь с PyQt, суть проблемы в следующем: имеется скрипт написанный на python и минималистичный интерфейс для него созданный с использованием PyQt , скрипт осуществляет сегментацию бинарного изображения(получает на вход изображение обрабатывает и выдаёт результат)
При попытке написать интерфейс для него я столкнулся с кучей проблем т.к до этого дела с Qt не имел и опыт в программировании минимален:
1. мне не понятно как передавать изображение которое я загружаю через QFileDialog в основной код для его обработки (плюс я использую Qpixmap в интефейсе а в основной программе PIL и нужно конвертировать изображения при передачи их туда сюда? ).
2. если я правильно понимаю моя программа должна работать по такому принципу get file from interface -> processing on main program -> show result into interface, но вот как обращаться из главной программы к своим функциям которые я в интерфейсе написал не понимаю..

Пожалуйста разъясните мне мои ошибки,или скажите где я могу почитать о них, ну или помогите доработать если вам не сложно

вот скриншоты того что у меня есть,и конечный результат который я пока не могу получить


это код самого скрипта
 #!/usr/bin/python
#_*_ coding: utf-8 _*_ 
import Image, ImageDraw
from PIL.ImageQt import ImageQt
import locale
import sys
import math, random
from itertools import product
from test_array_find import *
#from interface import *
import PIL.ImageOps 
from PyQt4.QtGui import *
from PyQt4.QtCore import *
loc=locale.getlocale()
locale.setlocale(locale.LC_ALL, ('RU','UTF8'))
def run(img):
    data = img.load()
    width, height = img.size
    # реализация системы непересекающихся множеств для нахождения связных областей 
    DSU = Disjoint_set_union()
 
    # первый проход
 
    # словарь который содержит пары меток
    labels = {}
 
    for y, x in product(range(height), range(width)):
 
        #
        # 
        #  представление нашей маски, с помощью которой будет производиться сканирование изображения
        #   -----------------------------------
        #   | x-1 , y-1 | x , y-1 | x+1 , y-1 |          | A | B | C |
        #   -----------------------------------          ------------- 
        #   |   x-1 ,y  |  x , y  | x+1 , y   |    =>    | D | E | F |
        #   -----------------------------------          -------------
        #   | x-1 , y+1 | x , y+1 | x+1 , y+1 |          | G | H | I |
        #   -----------------------------------           
        #
	# Сканирование изображениея начинаем с пикселя E который имеет координаты (x , y) 
	# пиксели A, B, C, D являются соседями пикселя E
	# Пиксели белого цвета являются пикселями фона,нас они не интересуют
	# если при сканировании маска выходит за границы изображения, то пиксели которые оказываются вне границ 
	# интерпретируются как белые
	#
 
	# если пиксель белый то он не является эллементом области,пропускаем и идём дальше
        if data[x, y] == 255:
            pass
	#
	# если пиксель b часть области и он черный, a,b,c являются его соседями,а значит они 
	# они пренадлежат одной и той же связной области, следовательно не нужно проверять их метки
	# достаточно просто присвоить метку b метке e
	#
	#
        elif y > 0 and data[x, y-1] == 0:
            labels[x, y] = labels[(x, y-1)]
	#
	# если пиксель c часть области изображения не являющийся фоном и он черный,
	# b - его сосед, но a и b нет, значит мф должны проветить метки у a и b
	#
	#
        elif x+1 < width and y > 0 and data[x+1, y-1] == 0:
 
            c = labels[(x+1, y-1)]
            labels[x, y] = c
	    #
	    # если пиксель a часть области изображения не являющийся фоном и он черный,  
	    # тогда a и c соеденены через e, следовательно мы должны объеденить их метки
            #
            if x > 0 and data[x-1, y-1] == 0:
                a = labels[(x-1, y-1)]
                DSU.union(c, a)
	    #
	    # если пиксель b часть области изображения не являющийся фоном и он черный,
	    # тогда d и c соедененны через e, значит мы должны объеденить их
            #
            elif x > 0 and data[x-1, y] == 0:
                d = labels[(x-1, y)]
                DSU.union(c, d)
        #
	# если пиксель a часть области изображения не являющийся фоном и он черный,
	# и т.к. мы знаем что что b и c белые, d будет соседом a, и у них уже одинаковые метки
	# то просто присваиваем метку  A к C
	#
        elif x > 0 and y > 0 and data[x-1, y-1] == 0:
            labels[x, y] = labels[(x-1, y-1)]
	#
	# если пиксель D часть области изображения не являющийся фоном и он черный,
	# и т.к. мы знаем что что a , b и c белые, то просто добавляем метку D к метке E
	#
	#
        elif x > 0 and data[x-1, y] == 0:
            labels[x, y] = labels[(x-1, y)]
	#
	# Все соседи пикселя белые, следовательно текущий пиксель получает новую метку
	#
        else: 
            labels[x, y] = DSU.makeLabel()
    # втрой проход
 
 
    # присваиваем конечные метки элементам связной области 
    DSU.flatten()
 
    colors = {}
    # Создаем изображение для отображения найденных областей в наглядной форме,присваяивая индивидуальный цвет определенной области 
    output_img = Image.new("RGB", (width, height))
    outdata = output_img.load()
    for (x, y) in labels:
 
	# Имя компонента связной области которому принадлежит текущая точка
        component = DSU.find(labels[(x, y)])
	# обновляем метку новыми данными
        labels[(x, y)] = component
 
	# присваиваем случайный цвет компонетнтам связной области
        if component not in colors: 
            colors[component] = (random.randrange(1,255,3),random.randrange(1,255,3),random.randrange(1,255,3))
	# раскрашиваем изображение присваивая цвет согласно принадлежности к связной области
        outdata[x, y] = colors[component]
    return (labels, output_img)
 
def main_seg():
    # открываем изображение
    img = Image.open("o2.jpg")
    #img = filedialogdemo.getfile()
    #производим пороговую обработку изображения,превращаем его в черно бело
	
    img = img.point(lambda p: p > 190 and 255)
    img = img.convert('1')
    #img = PIL.ImageOps.invert(img)
    #img= Image.open("out.jpg")
    
    #img.save(ing___)
    #
    # наша метка представленна в виде словаря,который содержит координаты и id 
    #    (x_coordinate, y_coordinate) : component_id
    #
    #  output_image конечный результат обработки в наглядном виде
    
    (labels, output_img) = run(img)
    output_img.save("o2_.jpg")
     
	#test----- 
def PILimageToQImage(pilimage):
    """converts a PIL image to QImage"""
    imageq = ImageQt(pilimage) #convert PIL image to a PIL.ImageQt object
    qimage = QImage(imageq) #cast PIL.ImageQt object to QImage object -that´s the trick!!!
    return qimage    
    #----------
    
def img_show():
    app = QApplication(sys.argv)
    #im = Image.open("out.jpg")
    #im.show()
    pim = Image.open("out.jpg")
    pim.show() #show pil image
    qim = PILimageToQImage(pim)
    pm = QPixmap(qim)
    #return qim
    lbl = QLabel()
    lbl.setPixmap(pm)
    lbl.show() #show label with qim image
    sys.exit(app.exec_())
    
    
if __name__ == "__main__": main()
# модуль test_array_find.py
#_*_ coding: utf-8 _*_ 
#Реализация системы неперескающихся множеств
# Parent - массив который содержит набор всех пренадлежаших множеству элементов
class Disjoint_set_union:
    def __init__(self):
	# Массив который содержит набор эквивалентностей между пикселями
        self.Parent = []
	# номер метки после того как она будет создана
        self.label = 0
    def makeLabel(self):
        r = self.label
        self.label += 1
        self.Parent.append(r)
        return r
    # Делает все узлы на пути из i указывающими на корень 
    def setRoot(self, i, root):
        while self.Parent[i] < i:
            j = self.Parent[i]
            self.Parent[i] = root
            i = j
        self.Parent[i] = root
      
      
    #test#
    def find(self, i):
      while self.Parent[i] < i:
            i = self.Parent[i]
      root = 	i
      self.setRoot(i, root)
      return root
    #
    # Объединяем два дерева содержащие ветви i и j
    # 
    def union(self, i, j):
        if i != j:
            #root = self.findRoot(i)
            #rootj = self.findRoot(j)
            while self.Parent[i] < i:
	      i = self.Parent[i]
	    root = i
	    while self.Parent[j] < j:
	      j = self.Parent[j]
	    rootj = j
	    
            if root > rootj: root = rootj
            self.setRoot(j, root)
            self.setRoot(i, root)
    
    #
    #flatten осуществляет выполнение аналитической фазы алгоритма 
    #присваивая окончательные метки связным областям
    #
    def flatten(self):
        for i in range(1, len(self.Parent)):
            self.Parent[i] = self.Parent[self.Parent[i]]
    

а это код интерфейса(только не кидайтесь помидорами) я просто абсолютно не понимаю как мне дописать его чтоб все заработало
 #!/usr/bin/python
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from connection8_main import *
from PIL import Image
from PIL.ImageQt import ImageQt
class filedialogdemo(QWidget):
    
   def __init__(self, parent = None):
      super(filedialogdemo, self).__init__(parent)
        
      self.setWindowTitle("SGMNT") 
      self.resize(500, 500) 
      
      
        
      layout = QVBoxLayout()
      
     
      
      self.btn = QPushButton("Upload your image")
      self.btn.clicked.connect(self.getfile)
      layout.addWidget(self.btn)
      
      self.btn2 = QPushButton("Segmentate")
      self.btn2.clicked.connect(self.segmentFile)
      layout.addWidget(self.btn2)
      
      
      self.btn1 = QPushButton("Save result")
      self.btn1.clicked.connect(self.saveFile)
      layout.addWidget(self.btn1)
      
      #self.btn3 = QPushButton("Show result")
      #self.btn3.clicked.connect(self.segment_result)
      #layout.addWidget(self.btn3)
      
      
      self.le = QLabel("image here")
      self.le1 = QLabel("result here")
      
      
      
        
      layout.addWidget(self.le)
      layout.addWidget(self.le1)
  
      self.setLayout(layout)
      
        
   def getfile(self):
      fname = QFileDialog.getOpenFileName(self, 'Open file', "Image files (*.*)")
      self.le.setPixmap(QPixmap(fname))
      
      
   def saveFile(self):
       #fname = QFileDialog.getOpenFileName(self, 'Open file', "Image files (*.*)")
       #self.le1.setPixmap(QPixmap(fname))
       filename = QFileDialog.getSaveFileName(self, "Save file", "", ".png")   
       self.le1.setPixmap(QPixmap(filename))
       
    #test-------   
   def segmentFile(self):
       main_seg()
       
   
         
def main():
   app = QApplication(sys.argv)
   ex = filedialogdemo()
   ex.show()
   sys.exit(app.exec_())
    
if __name__ == '__main__':
   main()


vic57
все можно через QImage сделать
пример интерфейса
 #coding:utf-8
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from random import randint
class View(QWidget):
    def __init__(self,parent=None):
        QWidget.__init__(self,parent)
        self.img = None
        self.lbl = QLabel()
        self.btnLoad = QPushButton("Load")
        self.btnRun = QPushButton("Run")
        self.btnSave= QPushButton("Save")
        grid = QGridLayout(self)
        grid.setMargin(1)
        grid.addWidget(self.lbl,0,0)
        grid.addWidget(self.btnLoad,1,0)
        grid.addWidget(self.btnRun,2,0)
        grid.addWidget(self.btnSave,3,0)
        self.btnLoad.clicked.connect(self.load)
        self.btnRun.clicked.connect(self.run)
        self.btnSave.clicked.connect(self.save)
    def load(self):
        fname = QFileDialog.getOpenFileName(None,"Load")
        self.img = QImage(fname)
        self.lbl.setPixmap(QPixmap.fromImage(self.img))
    def run(self):
        w  = self.img.width()
        h = self.img.height()
        for i in range(w):
            for j in range(h):
                rgb = self.img.pixel(i,j)
                red = qRed(rgb)
                green = qGreen(rgb)
                blue = qBlue(rgb)
                rand = randint(-50,50)
                self.img.setPixel(i,j,qRgb(red + rand,green + rand,blue + rand))
        self.lbl.setPixmap(QPixmap.fromImage(self.img))
    def save(self):
        fname = QFileDialog.getSaveFileName(None,"Save")
        self.img.save(fname)
        
if __name__=="__main__":
    a = QApplication([])
    w = View()
    w.move(0,0)
    w.show()
    a.exec_()
mgmn
Спасибо вам vic57, но мне не понятно следущее:
как я понимаю Qimage загружает мне мой файл(он получается попадает в память или QImage на него просто ссылается?) далее Qpixmap используя полученные QImage данные делает эту самую pixmap и отображает её в моем лейбле,изображение которое я загрузил с помощью Qimage еще в памяти и теперь, как я понимаю, я должен эти данные передать своему скрипту, он в свою очереть должен сконвертировать эти данные для того чтобы функции из PIL их поняли, далее обработать, и уже из обработанного изображения используя Qpixmap еще раз вывести результат в новый лейбл, а далее я нажму на кнопку save и сохраню результат.
Но я не понимаю как мне например обратьтся к QImage которая в функции Load из моего скрипта, через точку?у меня не выходит что-то..
ну и основная идея в том что я хочу использовать именно свой скрипт для сегментации а не что-то иное
vic57
ну так конвертируйте QImage -> PIL и используйте свой скрипт. или можете сразу PIL Image грузить.
self.img - в памяти
mgmn
собственно а как обращаться к этому self.img ?
я вот переделал кусок таким образом
     def PILimageToQImage(pilimage):
         imageq = ImageQt(pilimage) 
         qimage = QImage(imageq)
         return qimage 
    
    def load(self):
        pim = Image.open(unicode(QFileDialog().getOpenFileName()))
        #pim.show()
      
        qim = PILimageToQImage(pim)
        pm = QPixmap(qim)
        self.lbl.setPixmap(pm)
        return(pim)
я получается загружаю PIL изображение конвертирую его в QImage которое в свою очередь конвертирую в Pixmap(но эта вся ерунда работает кое как,постоянно ошибки сегментации и вылеты программы) и вывожу в label
далее я хочу обратьтся к своему загруженному PIL изображению,но как я не понимаю, пока максимум дочего я додумался это
 v = View()
img = v.load()
но таким образом я вызываю опть лоад
а если написать
img = v.load.pim
ничего не работает
помогите разобраться пожалуйста

я кстати пытался выести через print переменную pim и как раз получил адрес в памяти в котором хранится мое изображение,можно ли этот адрес использовать чтоб получить это изображение не используя переменную?хотя мне кажется что я уже огород нагородил

vic57
self.img нужен чтобы хранить загруженный рисунок. так и обращаться
 #coding:utf-8
from PIL import Image
from PIL.ImageQt import ImageQt
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from random import randint
def f(image):
    #тут что-то делаем с image
    print image,image.width,image.height
class View(QWidget):
    def __init__(self,parent=None):
        QWidget.__init__(self,parent)
        self.img = None
        self.lbl = QLabel()
        self.btnLoad = QPushButton("Load")
        self.btnRun = QPushButton("Run")
        self.btnSave= QPushButton("Save")
        grid = QGridLayout(self)
        grid.setMargin(1)
        grid.addWidget(self.lbl,0,0)
        grid.addWidget(self.btnLoad,1,0)
        grid.addWidget(self.btnRun,2,0)
        grid.addWidget(self.btnSave,3,0)
        self.btnLoad.clicked.connect(self.load)
        self.btnRun.clicked.connect(self.run)
        self.btnSave.clicked.connect(self.save)
    def load(self):
        fname = QFileDialog.getOpenFileName(None,"Load")
        self.img =  Image.open(str(fname))
        self.lbl.setPixmap(QPixmap.fromImage(ImageQt(self.img)))
    def run(self):
        f(self.img)           
    def save(self):
        fname = QFileDialog.getSaveFileName(None,"Save")
        self.img.save(str(fname),'PNG')
        
if __name__=="__main__":
    a = QApplication([])
    w = View()
    w.move(0,0)
    w.show()
    a.exec_()
но вообще Qt работает c форматами RGB - RGBA, для отображения на QLabel надо их использовать
mgmn
vic57 большое вам спасибо,вроде разобрался
vic57
вдогонку - в PIL Image есть функции для конвертации в Qt форматы :
    |  toqimage(self)
| Returns a QImage copy of this image
|
| toqpixmap(self)
| Returns a QPixmap copy of this image
|
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB