-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from harshmittal2210/paintProj
Auto Paint Project
- Loading branch information
Showing
5 changed files
with
306 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
from PyQt5 import QtWidgets, uic, QtCore, QtGui | ||
from PyQt5.QtWidgets import QFileDialog, QMessageBox | ||
from PyQt5.QtGui import QImage | ||
from PyQt5.QtCore import QObject, QThread, pyqtSignal | ||
import sys | ||
|
||
import cv2,imutils | ||
|
||
from ProcessImage import ProcessImage | ||
|
||
class PaintUI(QtWidgets.QMainWindow): | ||
def __init__(self): | ||
super(PaintUI,self).__init__() #Call the inherited classes __init__ method | ||
uic.loadUi('main.ui', self) | ||
|
||
## Add Code here | ||
self.fileName = None | ||
self.tmp = None | ||
self.cannyThreshold1 = 0 | ||
self.cannyThreshold2 = 100 | ||
|
||
self.processImage = ProcessImage() | ||
|
||
# Signal and Slots | ||
self.loadButton.clicked.connect(self.loadImage) | ||
self.saveButton.clicked.connect(self.saveImage) | ||
self.thresh1Slider.valueChanged['int'].connect(self.thresholdValue1) | ||
self.thresh2Slider.valueChanged['int'].connect(self.thresholdValue2) | ||
self.startPaintingButton.clicked.connect(self.initPainting) | ||
|
||
# Thread | ||
self.paintThread = None | ||
|
||
self.show() | ||
|
||
def loadImage(self): | ||
""" | ||
Load user selected photo and set to label | ||
""" | ||
self.fileName = QFileDialog.getOpenFileName(filter="Image (*.*)")[0] | ||
if not self.fileName: | ||
return | ||
self.img = cv2.imread(self.fileName) | ||
self.processImage.loadImage(self.img) | ||
self.setPhoto(self.img) | ||
|
||
def setPhoto(self,image): | ||
""" | ||
Set photo over label | ||
TODO: Resize according to the label and image size | ||
""" | ||
self.tmp = image | ||
image = imutils.resize(image,height=590) | ||
frame = cv2.cvtColor(image,cv2.COLOR_BGR2RGB) | ||
image = QImage(frame,frame.shape[1],frame.shape[0],frame.strides[0],QImage.Format_RGB888) | ||
self.label.setPixmap(QtGui.QPixmap.fromImage(image)) | ||
|
||
def thresholdValue1(self,value): | ||
self.cannyThreshold1 = value | ||
print(f"Thresh 1: {value}") | ||
self.update() | ||
|
||
def thresholdValue2(self,value): | ||
self.cannyThreshold2 = value | ||
print(f"Thresh 2: {value}") | ||
self.update() | ||
|
||
def update(self): | ||
if not self.fileName: | ||
print("Select Image First") | ||
return | ||
self.setPhoto(self.processImage.refreshImage(self.cannyThreshold1,self.cannyThreshold2)) | ||
|
||
def saveImage(self): | ||
cv2.imwrite("test.jpg",self.tmp) | ||
|
||
def initPainting(self): | ||
msg = QMessageBox() | ||
msg.setIcon(QMessageBox.Warning) | ||
|
||
msg.setWindowTitle("Important Information") | ||
msg.setText("Automated Painiting is about to start!!!") | ||
|
||
msg.setInformativeText("Make sure Paint app is open and visible. \n\n Select the pencil tool \ | ||
\nTo stop the code press CTRL + ALT + Del") | ||
|
||
# msg.setDetailedText("To stop the code press CTRL + ALT + Del") | ||
msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel) | ||
retval = msg.exec_() | ||
print ("value of pressed message box button:", retval) | ||
if retval==1024: | ||
self.paintThread = None | ||
def initPaintingThread(): | ||
self.processImage.startPainting() | ||
self.paintThread = QThread() | ||
self.paintThread.started.connect(initPaintingThread) | ||
self.paintThread.start() | ||
|
||
|
||
|
||
app = QtWidgets.QApplication(sys.argv) | ||
window = PaintUI() | ||
app.exec_() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import pyautogui | ||
import time | ||
import cv2 | ||
|
||
pyautogui.PAUSE = 0.01 | ||
|
||
class ProcessImage(): | ||
def __init__(self): | ||
self.canvas_start_ratio_x = 10.0/1920 | ||
self.canvas_start_ratio_y = 180.0/1080 | ||
|
||
self.canvas_size_ratio_x = 1070.0/1920 | ||
self.canvas_size_ratio_y = 670.0/1080 | ||
|
||
self.screenWidth, self.screenHeight = pyautogui.size() | ||
|
||
self.canvas_start_x = self.screenWidth*self.canvas_start_ratio_x | ||
self.canvas_start_y = self.screenHeight*self.canvas_start_ratio_y | ||
|
||
self.canvas_end_x = self.canvas_start_x + self.canvas_size_ratio_x*self.screenWidth | ||
self.canvas_end_y = self.canvas_start_y + self.canvas_size_ratio_y*self.screenHeight | ||
|
||
self.img = None | ||
|
||
def loadImage(self,img): | ||
self.img = img.copy() | ||
(self.h,self.w) = self.img.shape[:2] | ||
|
||
if self.h>self.w: | ||
self.img = self.image_resize(self.img,height=int(self.canvas_size_ratio_y*self.screenHeight)) | ||
else: | ||
self.img = self.image_resize(self.img,width=int(self.canvas_size_ratio_x*self.screenWidth)) | ||
|
||
self.image_pre_process() | ||
self.edge_detection() | ||
|
||
def refreshImage(self,thesh1,thresh2): | ||
self.edges = cv2.Canny(image=self.img_blur, threshold1=thesh1, threshold2=thresh2) | ||
return self.edges | ||
|
||
def image_resize(self,image, width = None, height = None, inter = cv2.INTER_AREA): | ||
dim = None | ||
(h, w) = image.shape[:2] | ||
if width is None and height is None: | ||
return None | ||
|
||
if width is None: | ||
r = height / float(h) | ||
dim = (int(w * r), height) | ||
else: | ||
r = width / float(w) | ||
dim = (width, int(h * r)) | ||
resized = cv2.resize(image, dim, interpolation = inter) | ||
return resized | ||
|
||
def image_pre_process(self): | ||
self.img_gray = cv2.cvtColor(self.img, cv2.COLOR_BGR2GRAY) | ||
self.img_blur = cv2.GaussianBlur(self.img_gray, (3,3), 0) | ||
|
||
def edge_detection(self): | ||
# self.sobelx = cv2.Sobel(src=self.img_blur, ddepth=cv2.CV_64F, dx=1, dy=0, ksize=5) # Sobel Edge | ||
# self.sobely = cv2.Sobel(src=self.img_blur, ddepth=cv2.CV_64F, dx=0, dy=1, ksize=5) # Sobel Edge | ||
# self.sobelxy = cv2.Sobel(src=self.img_blur, ddepth=cv2.CV_64F, dx=1, dy=1, ksize=5) # Combined X | ||
|
||
self.edges = cv2.Canny(image=self.img_blur, threshold1=30, threshold2=50) | ||
|
||
def startPainting(self): | ||
print("Starting Painting") | ||
|
||
pyautogui.moveTo(self.canvas_start_x, self.canvas_start_y) | ||
|
||
rows,cols = self.edges.shape | ||
for i in range(rows): | ||
for j in range(cols): | ||
if(self.edges[i,j]): | ||
pyautogui.click(self.canvas_start_x+j, self.canvas_start_y+i) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<ui version="4.0"> | ||
<class>MainWindow</class> | ||
<widget class="QMainWindow" name="MainWindow"> | ||
<property name="geometry"> | ||
<rect> | ||
<x>0</x> | ||
<y>0</y> | ||
<width>1123</width> | ||
<height>705</height> | ||
</rect> | ||
</property> | ||
<property name="windowTitle"> | ||
<string>MainWindow</string> | ||
</property> | ||
<widget class="QWidget" name="centralwidget"> | ||
<layout class="QGridLayout" name="gridLayout_2"> | ||
<item row="0" column="0"> | ||
<layout class="QGridLayout" name="gridLayout"> | ||
<item row="0" column="0" colspan="2"> | ||
<layout class="QHBoxLayout" name="horizontalLayout_3"> | ||
<item> | ||
<widget class="QLabel" name="label"> | ||
<property name="text"> | ||
<string/> | ||
</property> | ||
<property name="pixmap"> | ||
<pixmap>img/h3.jpg</pixmap> | ||
</property> | ||
</widget> | ||
</item> | ||
<item> | ||
<layout class="QHBoxLayout" name="horizontalLayout"> | ||
<item> | ||
<widget class="QSlider" name="thresh1Slider"> | ||
<property name="maximum"> | ||
<number>200</number> | ||
</property> | ||
<property name="singleStep"> | ||
<number>10</number> | ||
</property> | ||
<property name="value"> | ||
<number>30</number> | ||
</property> | ||
<property name="orientation"> | ||
<enum>Qt::Vertical</enum> | ||
</property> | ||
</widget> | ||
</item> | ||
<item> | ||
<widget class="QSlider" name="thresh2Slider"> | ||
<property name="maximum"> | ||
<number>300</number> | ||
</property> | ||
<property name="singleStep"> | ||
<number>10</number> | ||
</property> | ||
<property name="value"> | ||
<number>50</number> | ||
</property> | ||
<property name="orientation"> | ||
<enum>Qt::Vertical</enum> | ||
</property> | ||
</widget> | ||
</item> | ||
</layout> | ||
</item> | ||
</layout> | ||
</item> | ||
<item row="1" column="0"> | ||
<layout class="QHBoxLayout" name="horizontalLayout_2"> | ||
<item> | ||
<widget class="QPushButton" name="loadButton"> | ||
<property name="text"> | ||
<string>Load</string> | ||
</property> | ||
</widget> | ||
</item> | ||
<item> | ||
<widget class="QPushButton" name="saveButton"> | ||
<property name="text"> | ||
<string>Save</string> | ||
</property> | ||
</widget> | ||
</item> | ||
<item> | ||
<widget class="QPushButton" name="startPaintingButton"> | ||
<property name="text"> | ||
<string>Start Painting</string> | ||
</property> | ||
</widget> | ||
</item> | ||
</layout> | ||
</item> | ||
<item row="1" column="1"> | ||
<spacer name="horizontalSpacer"> | ||
<property name="orientation"> | ||
<enum>Qt::Horizontal</enum> | ||
</property> | ||
<property name="sizeHint" stdset="0"> | ||
<size> | ||
<width>40</width> | ||
<height>20</height> | ||
</size> | ||
</property> | ||
</spacer> | ||
</item> | ||
</layout> | ||
</item> | ||
</layout> | ||
</widget> | ||
<widget class="QMenuBar" name="menubar"> | ||
<property name="geometry"> | ||
<rect> | ||
<x>0</x> | ||
<y>0</y> | ||
<width>1123</width> | ||
<height>26</height> | ||
</rect> | ||
</property> | ||
</widget> | ||
<widget class="QStatusBar" name="statusbar"/> | ||
</widget> | ||
<resources/> | ||
<connections/> | ||
</ui> |