├── ImageProcessingGUI.py ├── PythonGUIScreenshot.png └── README.md /ImageProcessingGUI.py: -------------------------------------------------------------------------------- 1 | ################################################ 2 | # Image Processing GUI 3 | # Performs several image processing functions on 4 | # an imported image 5 | # using Python, Pyside, Qt, PIL 6 | # 7 | # Justin Poliachik 8 | # 10 December 2013 9 | ################################################ 10 | 11 | 12 | #!/usr/bin/python 13 | # -*- coding: utf-8 -*- 14 | 15 | import sys 16 | from PySide import QtGui 17 | from PySide import QtCore 18 | from PIL import Image 19 | from random import randint 20 | 21 | class MainWindow(QtGui.QWidget): 22 | 23 | def __init__(self): 24 | super(MainWindow, self).__init__() 25 | 26 | self.initUI() 27 | 28 | def initUI(self): 29 | 30 | print "Initializing" 31 | 32 | # File Pick Layout 33 | filePick = QtGui.QHBoxLayout() 34 | 35 | # Create a label which displays the path to our chosen file 36 | self.fileLabel = QtGui.QLabel('No file selected') 37 | filePick.addWidget(self.fileLabel) 38 | 39 | # Create a push button labelled 'choose' and add it to our layout 40 | fileBtn = QtGui.QPushButton('Choose file', self) 41 | filePick.addWidget(fileBtn) 42 | 43 | # Connect the clicked signal to the get_fname handler 44 | self.connect(fileBtn, QtCore.SIGNAL('clicked()'), self.get_fname) 45 | 46 | #Set the image to be blank at first 47 | pixmap = QtGui.QPixmap() 48 | self.imageLabel = QtGui.QLabel() 49 | self.imageLabel.setPixmap(pixmap) 50 | self.imageString = "" 51 | self.sliderValue = 0 52 | 53 | #Define layout boxes 54 | bottomBox = QtGui.QHBoxLayout() 55 | topBox = QtGui.QHBoxLayout() 56 | sideBox = QtGui.QVBoxLayout() 57 | sideBoxPad = QtGui.QHBoxLayout() 58 | 59 | #File picker on top 60 | topBox.addStretch(1) 61 | topBox.addLayout(filePick) 62 | topBox.addStretch(1) 63 | 64 | #Image in middle/right 65 | bottomBox.addStretch(1) 66 | bottomBox.addWidget(self.imageLabel) 67 | bottomBox.addStretch(1) 68 | 69 | #Buttons on left 70 | normalButton = QtGui.QPushButton("Normal") 71 | self.connect(normalButton, QtCore.SIGNAL('clicked()'), self.normal_image) 72 | addButton = QtGui.QPushButton("Add") 73 | self.connect(addButton, QtCore.SIGNAL('clicked()'), self.add) 74 | blurButton = QtGui.QPushButton("Blur") 75 | self.connect(blurButton, QtCore.SIGNAL('clicked()'), self.blur) 76 | contrastButton = QtGui.QPushButton("Contrast") 77 | self.connect(contrastButton, QtCore.SIGNAL('clicked()'), self.contrast) 78 | edgeDetectButton = QtGui.QPushButton("Edge Detect") 79 | self.connect(edgeDetectButton, QtCore.SIGNAL('clicked()'), self.edge_detect) 80 | invertButton = QtGui.QPushButton("Invert") 81 | self.connect(invertButton, QtCore.SIGNAL('clicked()'), self.invert) 82 | multiplyButton = QtGui.QPushButton("Multiply") 83 | self.connect(multiplyButton, QtCore.SIGNAL('clicked()'), self.multiply) 84 | sharpenButton = QtGui.QPushButton("Sharpen") 85 | self.connect(sharpenButton, QtCore.SIGNAL('clicked()'), self.sharpen) 86 | twoToneButton = QtGui.QPushButton("Two Tone") 87 | self.connect(twoToneButton, QtCore.SIGNAL('clicked()'), self.two_tone) 88 | 89 | #Slider 90 | sld = QtGui.QSlider(QtCore.Qt.Horizontal, self) 91 | sld.setFocusPolicy(QtCore.Qt.NoFocus) 92 | sld.setGeometry(30, 40, 100, 50) 93 | sld.valueChanged[int].connect(self.change_slider) 94 | 95 | sideBox.addStretch(1) 96 | sideBox.addWidget(normalButton) 97 | sideBox.addStretch(1) 98 | sideBox.addWidget(addButton) 99 | sideBox.addWidget(blurButton) 100 | sideBox.addWidget(contrastButton) 101 | sideBox.addWidget(edgeDetectButton) 102 | sideBox.addWidget(invertButton) 103 | sideBox.addWidget(multiplyButton) 104 | sideBox.addWidget(sharpenButton) 105 | sideBox.addWidget(twoToneButton) 106 | sideBox.addWidget(sld) 107 | sideBox.addStretch(1) 108 | sideBoxPad.addStretch(1) 109 | sideBoxPad.addLayout(sideBox) 110 | sideBoxPad.addStretch(1) 111 | 112 | #Set grid layout 113 | grid = QtGui.QGridLayout() 114 | grid.addLayout(topBox, 0, 1) 115 | grid.addLayout(sideBoxPad, 1, 0) 116 | grid.addLayout(bottomBox, 1, 1) 117 | self.setLayout(grid) 118 | 119 | self.setGeometry(300, 300, 800, 600) 120 | self.setWindowTitle('Image Processing Functions') 121 | 122 | self.show() 123 | 124 | #File Picker Function 125 | def get_fname(self): 126 | """ 127 | Handler called when 'choose file' is clicked 128 | """ 129 | # When you call getOpenFileName, a file picker dialog is created 130 | # and if the user selects a file, it's path is returned, and if not 131 | # (ie, the user cancels the operation) None is returned 132 | fname = QtGui.QFileDialog.getOpenFileName(self, 'Select file') 133 | print fname 134 | if fname: 135 | self.fileLabel.setText(fname[0]) 136 | self.load_image(fname[0]) 137 | else: 138 | self.fileLabel.setText("No file selected") 139 | 140 | #Load new image function 141 | def load_image(self, filepath): 142 | #Load the image into the label 143 | print "Loading Image" 144 | pixmap = QtGui.QPixmap(filepath) 145 | self.imageLabel.setPixmap(pixmap) 146 | self.imageString = filepath 147 | 148 | #Load new image function 149 | def set_image(self, image): 150 | #Load the image into the label 151 | self.imageLabel.setPixmap(image) 152 | 153 | #Load normal image 154 | def normal_image(self): 155 | #Load the image into the label 156 | print "Loading Image" 157 | pixmap = QtGui.QPixmap(self.imageString) 158 | self.imageLabel.setPixmap(pixmap) 159 | 160 | #Slider Changed 161 | def change_slider(self, value): 162 | self.sliderValue = value 163 | 164 | #---------------------------------------------------------------------- 165 | #Image Processing Functions 166 | #---------------------------------------------------------------- 167 | def add(self): 168 | print self.imageString 169 | if self.imageString: 170 | print "Processing" 171 | im = Image.open(self.imageString) 172 | imdata = im.tostring() 173 | imWidth = im.size[0] 174 | imHeight = im.size[1] 175 | 176 | # Convert image data from PIL image into a QImage 177 | ################################################ 178 | newqim = QtGui.QImage(imWidth, imHeight, QtGui.QImage.Format_ARGB32) 179 | for xstep in range(0,imWidth-1): 180 | for ystep in range(0,imHeight-1): 181 | # PIL uses getpixel and putpixel 182 | pixelValueTuple = im.getpixel((xstep,ystep)) 183 | pixelR = pixelValueTuple[0] 184 | pixelG = pixelValueTuple[1] 185 | pixelB = pixelValueTuple[2] 186 | 187 | addValue = self.sliderValue 188 | pixelR += addValue 189 | pixelG += addValue 190 | pixelB += addValue 191 | 192 | if pixelR > 255: 193 | pixelR = 255 194 | if pixelG > 255: 195 | pixelG = 255 196 | if pixelB > 255: 197 | pixelB = 255 198 | 199 | if pixelR < 0: 200 | pixelR = 0 201 | if pixelG < 0: 202 | pixelG = 0 203 | if pixelB < 0: 204 | pixelB = 0 205 | 206 | copiedValue = QtGui.qRgb(pixelR, pixelG, pixelB) 207 | # QImage uses pixel and setpixel 208 | newqim.setPixel(xstep, ystep, copiedValue) 209 | 210 | #newqim.save('result.jpg') 211 | 212 | # Put image data in a pixmap for display. 213 | # PIL Images and QImages may be used for read, write, manipulate. 214 | # QPixmaps are used for Qt GUI display. 215 | ################################################ 216 | #pix = QPixmap.fromImage(qim) # Pixmap for display using QImage 217 | pix = QtGui.QPixmap.fromImage(newqim) 218 | self.set_image(pix) 219 | 220 | 221 | 222 | #Blur 223 | def blur(self): 224 | if self.imageString: 225 | print "Processing" 226 | im = Image.open(self.imageString) 227 | imdata = im.tostring() 228 | imWidth = im.size[0] 229 | imHeight = im.size[1] 230 | 231 | # Convert image data from PIL image into a QImage 232 | ################################################ 233 | newqim = QtGui.QImage(imWidth, imHeight, QtGui.QImage.Format_ARGB32) 234 | for xstep in range(0,imWidth-1): 235 | for ystep in range(0,imHeight-1): 236 | # PIL uses getpixel and putpixel 237 | pixelValueTuple = im.getpixel((xstep,ystep)) 238 | pixelR = pixelValueTuple[0] 239 | pixelG = pixelValueTuple[1] 240 | pixelB = pixelValueTuple[2] 241 | 242 | averageR = 0 243 | averageG = 0 244 | averageB = 0 245 | 246 | # Ignore pixels on top and left borders 247 | if(xstep > 0 and xstep < imWidth-1): 248 | if(ystep > 0 and ystep < imHeight-1): 249 | averageR = pixelR*.11111 250 | averageG = pixelG*.11111 251 | averageB = pixelB*.11111 252 | #top left 253 | offsetpixel = im.getpixel((xstep-1,ystep-1)) 254 | averageR = averageR + (offsetpixel[0]*.11111) 255 | averageG = averageG + (offsetpixel[1]*.11111) 256 | averageB = averageB + (offsetpixel[2]*.11111) 257 | #top center 258 | offsetpixel = im.getpixel((xstep,ystep-1)) 259 | averageR = averageR + (offsetpixel[0]*.11111) 260 | averageG = averageG + (offsetpixel[1]*.11111) 261 | averageB = averageB + (offsetpixel[2]*.11111) 262 | #top right 263 | offsetpixel = im.getpixel((xstep+1,ystep-1)) 264 | averageR = averageR + (offsetpixel[0]*.11111) 265 | averageG = averageG + (offsetpixel[1]*.11111) 266 | averageB = averageB + (offsetpixel[2]*.11111) 267 | #center left 268 | offsetpixel = im.getpixel((xstep-1,ystep)) 269 | averageR = averageR + (offsetpixel[0]*.11111) 270 | averageG = averageG + (offsetpixel[1]*.11111) 271 | averageB = averageB + (offsetpixel[2]*.11111) 272 | #center right 273 | offsetpixel = im.getpixel((xstep+1,ystep)) 274 | averageR = averageR + (offsetpixel[0]*.11111) 275 | averageG = averageG + (offsetpixel[1]*.11111) 276 | averageB = averageB + (offsetpixel[2]*.11111) 277 | #bottom left 278 | offsetpixel = im.getpixel((xstep-1,ystep+1)) 279 | averageR = averageR + (offsetpixel[0]*.11111) 280 | averageG = averageG + (offsetpixel[1]*.11111) 281 | averageB = averageB + (offsetpixel[2]*.11111) 282 | #bottom center 283 | offsetpixel = im.getpixel((xstep,ystep+1)) 284 | averageR = averageR + (offsetpixel[0]*.11111) 285 | averageG = averageG + (offsetpixel[1]*.11111) 286 | averageB = averageB + (offsetpixel[2]*.11111) 287 | #bottom right 288 | offsetpixel = im.getpixel((xstep+1,ystep+1)) 289 | averageR = averageR + (offsetpixel[0]*.11111) 290 | averageG = averageG + (offsetpixel[1]*.11111) 291 | averageB = averageB + (offsetpixel[2]*.11111) 292 | 293 | pixelR = averageR 294 | pixelG = averageG 295 | pixelB = averageB 296 | 297 | if pixelR > 255: 298 | pixelR = 255 299 | if pixelG > 255: 300 | pixelG = 255 301 | if pixelB > 255: 302 | pixelB = 255 303 | 304 | if pixelR < 0: 305 | pixelR = 0 306 | if pixelG < 0: 307 | pixelG = 0 308 | if pixelB < 0: 309 | pixelB = 0 310 | 311 | copiedValue = QtGui.qRgb(pixelR, pixelG, pixelB) 312 | # QImage uses pixel and setpixel 313 | newqim.setPixel(xstep, ystep, copiedValue) 314 | 315 | pix = QtGui.QPixmap.fromImage(newqim) 316 | self.set_image(pix) 317 | 318 | 319 | 320 | #Contrast 321 | def contrast(self): 322 | print self.imageString 323 | if self.imageString: 324 | print "Processing" 325 | im = Image.open(self.imageString) 326 | imdata = im.tostring() 327 | imWidth = im.size[0] 328 | imHeight = im.size[1] 329 | 330 | factor = (self.sliderValue*2.0)/100.0 331 | 332 | # Convert image data from PIL image into a QImage 333 | ################################################ 334 | newqim = QtGui.QImage(imWidth, imHeight, QtGui.QImage.Format_ARGB32) 335 | for xstep in range(0,imWidth-1): 336 | for ystep in range(0,imHeight-1): 337 | # PIL uses getpixel and putpixel 338 | pixelValueTuple = im.getpixel((xstep,ystep)) 339 | pixelR = pixelValueTuple[0] 340 | pixelG = pixelValueTuple[1] 341 | pixelB = pixelValueTuple[2] 342 | 343 | pixelR = (factor * (pixelR - 128)) + 128 344 | pixelG = (factor * (pixelG - 128)) + 128 345 | pixelB = (factor * (pixelB - 128)) + 128 346 | 347 | if pixelR > 255: 348 | pixelR = 255 349 | if pixelG > 255: 350 | pixelG = 255 351 | if pixelB > 255: 352 | pixelB = 255 353 | 354 | if pixelR < 0: 355 | pixelR = 0 356 | if pixelG < 0: 357 | pixelG = 0 358 | if pixelB < 0: 359 | pixelB = 0 360 | 361 | copiedValue = QtGui.qRgb(pixelR, pixelG, pixelB) 362 | # QImage uses pixel and setpixel 363 | newqim.setPixel(xstep, ystep, copiedValue) 364 | 365 | pix = QtGui.QPixmap.fromImage(newqim) 366 | self.set_image(pix) 367 | 368 | 369 | 370 | #Edge Detect 371 | def edge_detect(self): 372 | if self.imageString: 373 | print "Processing" 374 | im = Image.open(self.imageString) 375 | imdata = im.tostring() 376 | imWidth = im.size[0] 377 | imHeight = im.size[1] 378 | 379 | # Convert image data from PIL image into a QImage 380 | ################################################ 381 | newqim = QtGui.QImage(imWidth, imHeight, QtGui.QImage.Format_ARGB32) 382 | for xstep in range(0,imWidth-1): 383 | for ystep in range(0,imHeight-1): 384 | # PIL uses getpixel and putpixel 385 | pixelValueTuple = im.getpixel((xstep,ystep)) 386 | pixelR = pixelValueTuple[0] 387 | pixelG = pixelValueTuple[1] 388 | pixelB = pixelValueTuple[2] 389 | 390 | averageR = 0 391 | averageG = 0 392 | averageB = 0 393 | 394 | # Ignore pixels on top and left borders 395 | if(xstep > 0 and xstep < imWidth-1): 396 | if(ystep > 0 and ystep < imHeight-1): 397 | averageR = pixelR*8 398 | averageG = pixelG*8 399 | averageB = pixelB*8 400 | #top left 401 | offsetpixel = im.getpixel((xstep-1,ystep-1)) 402 | averageR = averageR + (offsetpixel[0]*-1) 403 | averageG = averageG + (offsetpixel[1]*-1) 404 | averageB = averageB + (offsetpixel[2]*-1) 405 | #top center 406 | offsetpixel = im.getpixel((xstep,ystep-1)) 407 | averageR = averageR + (offsetpixel[0]*-1) 408 | averageG = averageG + (offsetpixel[1]*-1) 409 | averageB = averageB + (offsetpixel[2]*-1) 410 | #top right 411 | offsetpixel = im.getpixel((xstep+1,ystep-1)) 412 | averageR = averageR + (offsetpixel[0]*-1) 413 | averageG = averageG + (offsetpixel[1]*-1) 414 | averageB = averageB + (offsetpixel[2]*-1) 415 | #center left 416 | offsetpixel = im.getpixel((xstep-1,ystep)) 417 | averageR = averageR + (offsetpixel[0]*-1) 418 | averageG = averageG + (offsetpixel[1]*-1) 419 | averageB = averageB + (offsetpixel[2]*-1) 420 | #center right 421 | offsetpixel = im.getpixel((xstep+1,ystep)) 422 | averageR = averageR + (offsetpixel[0]*-1) 423 | averageG = averageG + (offsetpixel[1]*-1) 424 | averageB = averageB + (offsetpixel[2]*-1) 425 | #bottom left 426 | offsetpixel = im.getpixel((xstep-1,ystep+1)) 427 | averageR = averageR + (offsetpixel[0]*-1) 428 | averageG = averageG + (offsetpixel[1]*-1) 429 | averageB = averageB + (offsetpixel[2]*-1) 430 | #bottom center 431 | offsetpixel = im.getpixel((xstep,ystep+1)) 432 | averageR = averageR + (offsetpixel[0]*-1) 433 | averageG = averageG + (offsetpixel[1]*-1) 434 | averageB = averageB + (offsetpixel[2]*-1) 435 | #bottom right 436 | offsetpixel = im.getpixel((xstep+1,ystep+1)) 437 | averageR = averageR + (offsetpixel[0]*-1) 438 | averageG = averageG + (offsetpixel[1]*-1) 439 | averageB = averageB + (offsetpixel[2]*-1) 440 | 441 | pixelR = averageR 442 | pixelG = averageG 443 | pixelB = averageB 444 | 445 | if pixelR > 255: 446 | pixelR = 255 447 | if pixelG > 255: 448 | pixelG = 255 449 | if pixelB > 255: 450 | pixelB = 255 451 | 452 | if pixelR < 0: 453 | pixelR = 0 454 | if pixelG < 0: 455 | pixelG = 0 456 | if pixelB < 0: 457 | pixelB = 0 458 | 459 | copiedValue = QtGui.qRgb(pixelR, pixelG, pixelB) 460 | # QImage uses pixel and setpixel 461 | newqim.setPixel(xstep, ystep, copiedValue) 462 | 463 | pix = QtGui.QPixmap.fromImage(newqim) 464 | self.set_image(pix) 465 | 466 | 467 | #Invert 468 | def invert(self): 469 | if self.imageString: 470 | print "Processing" 471 | im = Image.open(self.imageString) 472 | imdata = im.tostring() 473 | imWidth = im.size[0] 474 | imHeight = im.size[1] 475 | 476 | # Convert image data from PIL image into a QImage 477 | ################################################ 478 | newqim = QtGui.QImage(imWidth, imHeight, QtGui.QImage.Format_ARGB32) 479 | for xstep in range(0,imWidth-1): 480 | for ystep in range(0,imHeight-1): 481 | # PIL uses getpixel and putpixel 482 | pixelValueTuple = im.getpixel((xstep,ystep)) 483 | pixelR = pixelValueTuple[0] 484 | pixelG = pixelValueTuple[1] 485 | pixelB = pixelValueTuple[2] 486 | 487 | pixelR = 255-pixelR 488 | pixelG = 255-pixelG 489 | pixelB = 255-pixelB 490 | 491 | if pixelR > 255: 492 | pixelR = 255 493 | if pixelG > 255: 494 | pixelG = 255 495 | if pixelB > 255: 496 | pixelB = 255 497 | 498 | if pixelR < 0: 499 | pixelR = 0 500 | if pixelG < 0: 501 | pixelG = 0 502 | if pixelB < 0: 503 | pixelB = 0 504 | 505 | copiedValue = QtGui.qRgb(pixelR, pixelG, pixelB) 506 | # QImage uses pixel and setpixel 507 | newqim.setPixel(xstep, ystep, copiedValue) 508 | 509 | pix = QtGui.QPixmap.fromImage(newqim) 510 | self.set_image(pix) 511 | 512 | 513 | 514 | #Multiply 515 | def multiply(self): 516 | if self.imageString: 517 | print "Processing" 518 | im = Image.open(self.imageString) 519 | imdata = im.tostring() 520 | imWidth = im.size[0] 521 | imHeight = im.size[1] 522 | 523 | multValue = (self.sliderValue*2.0)/100.0 524 | 525 | # Convert image data from PIL image into a QImage 526 | ################################################ 527 | newqim = QtGui.QImage(imWidth, imHeight, QtGui.QImage.Format_ARGB32) 528 | for xstep in range(0,imWidth-1): 529 | for ystep in range(0,imHeight-1): 530 | # PIL uses getpixel and putpixel 531 | pixelValueTuple = im.getpixel((xstep,ystep)) 532 | pixelR = pixelValueTuple[0] 533 | pixelG = pixelValueTuple[1] 534 | pixelB = pixelValueTuple[2] 535 | 536 | pixelR *= multValue 537 | pixelG *= multValue 538 | pixelB *= multValue 539 | 540 | if pixelR > 255: 541 | pixelR = 255 542 | if pixelG > 255: 543 | pixelG = 255 544 | if pixelB > 255: 545 | pixelB = 255 546 | 547 | if pixelR < 0: 548 | pixelR = 0 549 | if pixelG < 0: 550 | pixelG = 0 551 | if pixelB < 0: 552 | pixelB = 0 553 | 554 | copiedValue = QtGui.qRgb(pixelR, pixelG, pixelB) 555 | # QImage uses pixel and setpixel 556 | newqim.setPixel(xstep, ystep, copiedValue) 557 | 558 | pix = QtGui.QPixmap.fromImage(newqim) 559 | self.set_image(pix) 560 | 561 | 562 | 563 | 564 | #Sharpen 565 | def sharpen(self): 566 | if self.imageString: 567 | print "Processing" 568 | im = Image.open(self.imageString) 569 | imdata = im.tostring() 570 | imWidth = im.size[0] 571 | imHeight = im.size[1] 572 | 573 | # Convert image data from PIL image into a QImage 574 | ################################################ 575 | newqim = QtGui.QImage(imWidth, imHeight, QtGui.QImage.Format_ARGB32) 576 | for xstep in range(0,imWidth-1): 577 | for ystep in range(0,imHeight-1): 578 | # PIL uses getpixel and putpixel 579 | pixelValueTuple = im.getpixel((xstep,ystep)) 580 | pixelR = pixelValueTuple[0] 581 | pixelG = pixelValueTuple[1] 582 | pixelB = pixelValueTuple[2] 583 | 584 | averageR = 0 585 | averageG = 0 586 | averageB = 0 587 | 588 | # Ignore pixels on top and left borders 589 | if(xstep > 0 and xstep < imWidth-1): 590 | if(ystep > 0 and ystep < imHeight-1): 591 | averageR = pixelR*9 592 | averageG = pixelG*9 593 | averageB = pixelB*9 594 | #top left 595 | offsetpixel = im.getpixel((xstep-1,ystep-1)) 596 | averageR = averageR + (offsetpixel[0]*-1) 597 | averageG = averageG + (offsetpixel[1]*-1) 598 | averageB = averageB + (offsetpixel[2]*-1) 599 | #top center 600 | offsetpixel = im.getpixel((xstep,ystep-1)) 601 | averageR = averageR + (offsetpixel[0]*-1) 602 | averageG = averageG + (offsetpixel[1]*-1) 603 | averageB = averageB + (offsetpixel[2]*-1) 604 | #top right 605 | offsetpixel = im.getpixel((xstep+1,ystep-1)) 606 | averageR = averageR + (offsetpixel[0]*-1) 607 | averageG = averageG + (offsetpixel[1]*-1) 608 | averageB = averageB + (offsetpixel[2]*-1) 609 | #center left 610 | offsetpixel = im.getpixel((xstep-1,ystep)) 611 | averageR = averageR + (offsetpixel[0]*-1) 612 | averageG = averageG + (offsetpixel[1]*-1) 613 | averageB = averageB + (offsetpixel[2]*-1) 614 | #center right 615 | offsetpixel = im.getpixel((xstep+1,ystep)) 616 | averageR = averageR + (offsetpixel[0]*-1) 617 | averageG = averageG + (offsetpixel[1]*-1) 618 | averageB = averageB + (offsetpixel[2]*-1) 619 | #bottom left 620 | offsetpixel = im.getpixel((xstep-1,ystep+1)) 621 | averageR = averageR + (offsetpixel[0]*-1) 622 | averageG = averageG + (offsetpixel[1]*-1) 623 | averageB = averageB + (offsetpixel[2]*-1) 624 | #bottom center 625 | offsetpixel = im.getpixel((xstep,ystep+1)) 626 | averageR = averageR + (offsetpixel[0]*-1) 627 | averageG = averageG + (offsetpixel[1]*-1) 628 | averageB = averageB + (offsetpixel[2]*-1) 629 | #bottom right 630 | offsetpixel = im.getpixel((xstep+1,ystep+1)) 631 | averageR = averageR + (offsetpixel[0]*-1) 632 | averageG = averageG + (offsetpixel[1]*-1) 633 | averageB = averageB + (offsetpixel[2]*-1) 634 | 635 | pixelR = averageR 636 | pixelG = averageG 637 | pixelB = averageB 638 | 639 | if pixelR > 255: 640 | pixelR = 255 641 | if pixelG > 255: 642 | pixelG = 255 643 | if pixelB > 255: 644 | pixelB = 255 645 | 646 | if pixelR < 0: 647 | pixelR = 0 648 | if pixelG < 0: 649 | pixelG = 0 650 | if pixelB < 0: 651 | pixelB = 0 652 | 653 | copiedValue = QtGui.qRgb(pixelR, pixelG, pixelB) 654 | # QImage uses pixel and setpixel 655 | newqim.setPixel(xstep, ystep, copiedValue) 656 | 657 | pix = QtGui.QPixmap.fromImage(newqim) 658 | self.set_image(pix) 659 | 660 | 661 | #Custom Function two_tone 662 | #Converts the image to grayscale using the luminosity formula 663 | #Determines a cutoff point based off the slider value 664 | #Pixels are either white or black based on the cutoff point 665 | def two_tone(self): 666 | if self.imageString: 667 | print "Processing" 668 | im = Image.open(self.imageString) 669 | imdata = im.tostring() 670 | imWidth = im.size[0] 671 | imHeight = im.size[1] 672 | 673 | cutoffValue = self.sliderValue*2.55 674 | 675 | # Convert image data from PIL image into a QImage 676 | ################################################ 677 | newqim = QtGui.QImage(imWidth, imHeight, QtGui.QImage.Format_ARGB32) 678 | for xstep in range(0,imWidth-1): 679 | for ystep in range(0,imHeight-1): 680 | # PIL uses getpixel and putpixel 681 | pixelValueTuple = im.getpixel((xstep,ystep)) 682 | pixelR = pixelValueTuple[0] 683 | pixelG = pixelValueTuple[1] 684 | pixelB = pixelValueTuple[2] 685 | 686 | #Using luminosity formula 687 | grayPixel = (pixelR*.21) + (pixelG*.71) + (pixelB*.07) 688 | 689 | if(grayPixel > cutoffValue): 690 | grayPixel = 255 691 | else: 692 | grayPixel = 1 693 | 694 | if grayPixel > 255: 695 | grayPixel = 255 696 | if grayPixel < 0: 697 | grayPixel = 0 698 | 699 | copiedValue = QtGui.qRgb(grayPixel, grayPixel, grayPixel) 700 | # QImage uses pixel and setpixel 701 | newqim.setPixel(xstep, ystep, copiedValue) 702 | 703 | pix = QtGui.QPixmap.fromImage(newqim) 704 | self.set_image(pix) 705 | 706 | 707 | 708 | 709 | def main(): 710 | 711 | app = QtGui.QApplication(sys.argv) 712 | ex = MainWindow() 713 | sys.exit(app.exec_()) 714 | 715 | 716 | if __name__ == '__main__': 717 | main() -------------------------------------------------------------------------------- /PythonGUIScreenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpoliachik/PythonImageProcessing/0c1fb2bb73374ec010b16ace224da7af057b102a/PythonGUIScreenshot.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | PythonImageProcessing 2 | ===================== 3 | 4 | Python GUI to perform basic image processing functions. 5 | 6 | Using PySide for GUI and PIL for image handling. 7 | 8 | 9 | WARNING: This is not meant to be efficient. All work is done on the main thread, and Python is not meant for low level functions such as image processing. This program is meant for learning purposes. 10 | 11 | 12 | ![alt tag](https://raw2.github.com/Jpoliachik/PythonImageProcessing/master/PythonGUIScreenshot.png) 13 | --------------------------------------------------------------------------------