question regarding drawing squares on uploaded image

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>from PyQt5.QtGui import QMouseEvent, QPixmap, QImage, QPainter, QPen, QColor
from PyQt5.QtWidgets import (
QApplication,
QWidget,
QPushButton,
QLabel,
QVBoxLayout,
QHBoxLayout,
QFileDialog,
QLineEdit,
QRadioButton,
QMessageBox,
QInputDialog,
)
from PIL import Image, ImageEnhance, ImageColor
from PyQt5.QtCore import Qt, QPoint, QRect
from PyQt5.QtGui import QPixmap, QPainter, QFont
from PyQt5 import QtGui
import os
import sys
import cv2
import math
class mainwindow(QWidget):
def __init__(self):
super().__init__()
self.top = 200
self.left = 500
self.width = 700
self.height = 700
self.imageheight = 600
self.imagewidth = 600
self.setWindowTitle("face tagging")
self.setGeometry(self.left, self.top, self.width, self.height)
self.label = QLabel("image presented here ", self)
self.label.move(200, 200)
self.btn2 = QPushButton("image editor", self)
self.btn2.clicked.connect(self.editing_window)
self.btn3 = QPushButton("Locate face", self)
self.btn3.clicked.connect(self.findFace)
self.btn4 = QPushButton("delete faces", self)
self.btn4.clicked.connect(self.delete_false_face)
self.btn5 = QPushButton("add faces", self)
self.btn6 = QPushButton("name tag", self)
self.btn6.clicked.connect(self.createtagwindow)
self.btn5.clicked.connect(self.enabled)
self.imagepath = ""
self.fList = facelist()
self.delclick = False
self.enable = False
# QPixmap to draw on
self.pix = QtGui.QPixmap(self.imagepath)
self.begin = QPoint()
self.destination = QPoint()
vbox = QHBoxLayout()
vbox.addWidget(self.btn2)
vbox.addWidget(self.btn3)
vbox.addWidget(self.btn4)
vbox.addWidget(self.btn5)
buttons_widget = QWidget()
buttons_widget.setLayout(vbox)
hbox = QHBoxLayout()
hbox.addWidget(self.label)
hbox.addWidget(buttons_widget)
self.setLayout(hbox)
self.setwidget()
def setwidget(self):
self.btn1 = QPushButton("upload here", self)
self.btn1.clicked.connect(self.obtainphoto)
def editing_window(self):
self.editwin = createwindow(self)
self.editwin.show()
def obtainphoto(self):
fname = QFileDialog.getOpenFileName(self, "open file")
self.imagepath = fname[0]
self.originalpath = fname[0]
self.renderimage()
def renderimage(self):
self.pixmap = QPixmap(self.imagepath)
self.pixmap_resized = self.pixmap.scaled(
self.imagewidth,
self.imageheight,
Qt.KeepAspectRatio,
Qt.SmoothTransformation,
)
self.label.setPixmap(self.pixmap_resized)
self.pix = QtGui.QPixmap(self.pixmap_resized)
def display_image(self, img):
height, width, colors = img.shape
bytesperline = 3 * width
image = QImage(img.data, width, height, bytesperline, QImage.Format_RGB888)
self.image = image.rgbSwapped()
self.label.setPixmap(QPixmap.fromImage(self.image))
def findFace(self):
face_cascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
img = cv2.imread(self.imagepath, cv2.IMREAD_COLOR)
img = cv2.resize(img, (self.imagewidth, self.imageheight))
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 2, 1).tolist()
for x, y, w, h in faces:
self.fList.append_face(x, y, w, h)
cv2.rectangle(img, (x, y), (x + w, y + h), (255, 255, 0), 2)
self.display_image(img)
def createtagwindow(self):
self.tagwin = tagwindow()
self.tagwin.setwidgets(self)
self.tagwin.show()
def delete_false_face(self):
if self.label.pixmap() is None:
print("Photo is not present within the given area")
elif self.fList is None or self.fList.count_face() == 0:
print("No face is detected")
else:
print("Which face do you want to delete?")
self.delclick = True
def createaddfacewin(self):
self.addfacewin = addfacewindow(self)
self.addfacewin.setwidgets(self)
self.addfacewin.show()
def mousePressEvent(self, event):
if event.buttons() & Qt.LeftButton and self.enable:
self.begin = event.pos()
self.destination = self.begin
self.update()
def mouseMoveEvent(self, event):
if event.buttons() & Qt.LeftButton and self.enable:
self.destination = event.pos()
self.update()
def mouseReleaseEvent(self, event):
if event.button() & Qt.LeftButton and self.enable:
rect = self.get_rect_from_center(self.begin, self.destination)
painter = QPainter(self.pix)
painter.setPen(QPen(QColor("blue"), 3))
painter.drawRect(rect.normalized())
self.fList.append_face(rect.x(), rect.y(), rect.width(), rect.height())
self.begin, self.destination = QPoint(), QPoint()
self.update()
def paintEvent(self, event):
painter = QPainter(self)
if self.pix:
painter.drawPixmap(0, 0, self.pix)
if not self.begin.isNull() and not self.destination.isNull() and self.enable:
painter.setPen(QPen(QColor("blue"), 3))
rect = self.get_rect_from_center(self.begin, self.destination)
painter.drawRect(rect.normalized())
def get_rect_from_center(self, center, edge):
width = abs(edge.x() - center.x()) * 2
height = abs(edge.y() - center.y()) * 2
top_left = QPoint(center.x() - width // 2, center.y() - height // 2)
bottom_right = QPoint(center.x() + width // 2, center.y() + height // 2)
return QRect(top_left, bottom_right)
def enabled(self):
self.enable = True
class createwindow(QWidget):
def __init__(self, mainwindow_instance):
super().__init__()
self.mainwindow_instance = mainwindow_instance
self.width = 350
self.height = 350
self.setWindowTitle("Image Editor")
self.setGeometry(500, 200, self.width, self.height)
self.setwidget()
def setwidget(self):
self.labelwidth = QLabel("width editor", self)
self.labelwidth.move(20, 20)
self.textwidth = QLineEdit("width", self)
self.textwidth.move(20, 50)
self.labelheight = QLabel("height editor", self)
self.labelheight.move(20, 100)
self.textheight = QLineEdit("height", self)
self.textheight.move(20, 130)
self.labelcolor = QLabel("adjust photo color", self)
self.labelcolor.move(20, 180)
self.radiobtn1 = QRadioButton("original", self)
self.radiobtn1.setChecked(True)
self.radiobtn1.move(20, 210)
self.radiochecked = "original"
self.radiobtn2 = QRadioButton("grey", self)
self.radiobtn2.move(20, 240)
self.radiobtn3 = QRadioButton("red", self)
self.radiobtn3.move(20, 270)
self.radiobtn4 = QRadioButton("green", self)
self.radiobtn4.move(20, 300)
self.radiobtn5 = QRadioButton("blue", self)
self.radiobtn5.move(20, 330)
self.radiobtn6 = QRadioButton("turquoise", self)
self.radiobtn6.move(90, 210)
self.radiobtn7 = QRadioButton("orange", self)
self.radiobtn7.move(90, 240)
self.btn_confirm = QPushButton("confirm changes", self)
self.btn_confirm.move(230, 20)
self.btn_confirm.clicked.connect(self.editimage)
self.radiobtn1.toggled.connect(self.btnstate)
self.radiobtn2.toggled.connect(self.btnstate)
self.radiobtn3.toggled.connect(self.btnstate)
self.radiobtn4.toggled.connect(self.btnstate)
self.radiobtn5.toggled.connect(self.btnstate)
self.radiobtn6.toggled.connect(self.btnstate)
self.radiobtn7.toggled.connect(self.btnstate)
def btnstate(self):
radiobtn = self.sender()
self.radiochecked = radiobtn.text()
def editimage(self):
img = Image.open(self.mainwindow_instance.originalpath)
img = img.convert("RGB")
if self.radiochecked == "original":
img_edited = img
elif self.radiochecked == "grey":
img_edited = img.convert("L")
elif self.radiochecked == "red":
red = (
0.90,
0.36,
0.18,
0.00,
0.11,
0.72,
0.07,
0.00,
0.02,
0.12,
0.95,
0.00,
)
img_edited = img.convert("RGB", red)
elif self.radiochecked == "blue":
blue = (
0.18,
0.36,
0.90,
0.00,
0.07,
0.72,
0.11,
0.00,
0.95,
0.12,
0.02,
0.00,
)
img_edited = img.convert("RGB", blue)
elif self.radiochecked == "green":
green = (
0.18,
0.90,
0.36,
0.00,
0.07,
0.11,
0.72,
0.00,
0.95,
0.02,
0.12,
0.00,
)
img_edited = img.convert("RGB", green)
elif self.radiochecked == "turquoise":
turquoise = (
0.18,
0.36,
0.90,
0.00,
0.72,
0.11,
0.07,
0.00,
0.12,
0.02,
0.95,
0.00,
)
img_edited = img.convert("RGB", turquoise)
elif self.radiochecked == "orange":
orange = (
0.95,
0.02,
0.12,
0.00,
0.11,
0.72,
0.07,
0.00,
0.18,
0.36,
0.90,
0.00,
)
img_edited = img.convert("RGB", orange)
if img_edited.mode == "RGBA":
img_edited = img_edited.convert("RGB")
img_edited.save("image_edited.jpg", "JPEG")
self.mainwindow_instance.imagepath = os.path.join(
os.getcwd(), "image_edited.jpg"
)
try:
imgwidth_edited = self.textwidth.text()
imgheight_edited = self.textheight.text()
if imgwidth_edited == "width":
imgwidth_edited = str(self.mainwindow_instance.imagewidth)
if imgheight_edited == "height":
imgheight_edited = str(self.mainwindow_instance.imageheight)
self.mainwindow_instance.imagewidth = int(imgwidth_edited)
self.mainwindow_instance.imageheight = int(imgheight_edited)
self.mainwindow_instance.renderimage()
self.close()
except ValueError:
QMessageBox.warning(
self,
"Invalid Input",
"Please enter valid integer values for width and height.",
)
class addfacewindow(QWidget):
def __init__(self, mainwindow):
super().__init__()
def setwidgets(self, mainwindow):
self.setGeometry(mainwindow.left, mainwindow.top, 200, 300)
self.mlabel = squarelabel(
mainwindow.imagepath,
mainwindow.imagewidth,
mainwindow.imageheight,
mainwindow.fList,
)
self.pixmap = QPixmap(mainwindow.imagepath)
self.pixmap_resized = self.pixmap.scaled(
mainwindow.imagewidth, mainwindow.imageheight
)
self.mlabel.setPixmap(self.pixmap_resized)
self.addface = QPushButton("add face", self)
self.addface.clicked.connect(lambda: self.mlabel.addface())
self.btnconfirm = QPushButton("confirm", self)
vbox = QVBoxLayout()
vbox.addWidget(self.addface)
vbox.addWidget(self.btnconfirm)
widgetbutton = QWidget()
widgetbutton.setLayout(vbox)
hbox = QHBoxLayout()
hbox.addWidget(self.mlabel)
hbox.addWidget(widgetbutton)
self.setLayout(hbox)
class tagwindow(mainwindow):
def __init__(self):
super().__init__()
def setwidgets(self, mainwindow):
self.setGeometry(self.left, self.top, 200, 300)
self.mlabel = taglabel(
mainwindow.imagepath, mainwindow.width, mainwindow.height, mainwindow.fList
)
self.btnSave = QPushButton("store this", self)
self.btnSave.clicked.connect(lambda: self.mlabel.saveFile())
self.btnOK = QPushButton("confirm", self)
self.btnOK.clicked.connect(lambda: self.finishTag(mainwindow))
vbox = QVBoxLayout()
vbox.addWidget(self.btnSave)
vbox.addWidget(self.btnOK)
button_widget = QWidget()
button_widget.setLayout(vbox)
hbox = QHBoxLayout()
hbox.addWidget(self.mlabel)
hbox.addWidget(button_widget)
self.setLayout(hbox)
class squarelabel(QLabel):
def __init__(self, imgpath, w, h, facelist):
super().__init__()
self.pixmap = QPixmap(imgpath)
self.pixmap_resized = self.pixmap.scaled(w, h)
self.setPixmap(self.pixmap_resized)
painter = QPainter(self.pixmap_resized)
painter.setPen(QPen(QColor("blue"), 3))
self.facelist = facelist
for f in self.facelist.face_list:
print(f.x, f.y, f.w, f.h)
painter.drawRect(f.x, f.y, f.w, f.h)
self.setPixmap(self.pixmap_resized)
self.left_clicking = False
def mousepressevent(self, event):
if event.button() == 1:
self.startX = event.x()
self.starty = event.y()
self.left_clicking = True
def mouserelease(self, event):
if event.button() == 1:
self.finishX = event.x()
self.finishY = event.y()
self.left_clicking = False
def mousemovement(self, event):
if self.left_clicking:
self.pixmap_temp = self.pixmap_resized.copy()
painter = QPainter(self.pixmap_temp)
painter.setPen(QPen(QColor("green"), 3))
painter.drawRect(
self.startX,
self.startY,
event.x() - self.startX,
event.y() - self.startY,
)
self.setPixmap(self.pixmap_temp)
def addface(self):
x, y, w, h = (
self.startX,
self.startY,
self.finishX - self.startX,
self.finishY - self.startY,
)
self.facelist.append_face(x, y, w, h)
painter = QPainter(self.pixmap_temp)
painter.setPen(QPen(QColor("blue"), 3))
painter.drawRect(x, y, w, h)
self.setPixmap(self.pixmap_resized)
def finishface(self, mainwindow):
mainwindow.label.setPixmap(self.mlabel.pixmap_resized)
self.close()
class taglabel(squarelabel):
def __init__(self, imgpath, w, h, facelist):
super().__init__(imgpath, w, h, facelist)
def mousepress(self, event):
for f in self.facelist.face_list:
if f.x <= event.x() <= f.x + f.w and f.y <= event.y() <= f.y + f.h:
print("face Id", f.id, f.name)
text, pressconfirm = QInputDialog.getText(
self, "input", "name:", QLineEdit.Normal
)
if pressconfirm and text != "":
f.name = text
break
self.drawnames()
def drawnames(self):
self.pixmap_temp = self.pixmap_resized.copy()
painter = QPainter(self.pixmap_temp)
painter.setPen(QPen(QColor("blue"), 3))
for f in self.facelist.face_list:
painter.drawText(f.x, f.y - 5, f.name)
painter.end()
self.setPixmap(self.pixmap_temp)
def saveFile(self):
text, confirmpress = QInputDialog.getText(
self, "file name inputter", "file name", QLineEdit.Normal
)
if confirmpress:
self.pixmap_temp.save(text + "jpg", "JPG")
def finishTag(self, mainwindow):
mainwindow.label.setPixmap(self.mlabel.pixmap_temp)
self.close()
def mouserelease(self, event):
pass
def mousemove(self, event):
pass
class facelist:
def __init__(self):
self.face_list = []
self.face_id = 0
def append_face(self, x, y, w, h, name=None):
face = Face(self.face_id, x, y, w, h, name)
self.face_list.append(face)
self.face_id += 1
def remove_face(self, face_id):
for face in self.face_list:
if face.id == face_id:
self.face_list.remove(face)
break
def count_face(self):
return len(self.face_list)
class Face:
def __init__(self, face_id, x, y, w, h, name=None):
self.id = face_id
self.x = x
self.y = y
self.w = w
self.h = h
self.name = name
if __name__ == '__main__':
app = QApplication(sys.argv)
mainwin = mainwindow()
mainwin.show()
sys.exit(app.exec_())
</code>
<code>from PyQt5.QtGui import QMouseEvent, QPixmap, QImage, QPainter, QPen, QColor from PyQt5.QtWidgets import ( QApplication, QWidget, QPushButton, QLabel, QVBoxLayout, QHBoxLayout, QFileDialog, QLineEdit, QRadioButton, QMessageBox, QInputDialog, ) from PIL import Image, ImageEnhance, ImageColor from PyQt5.QtCore import Qt, QPoint, QRect from PyQt5.QtGui import QPixmap, QPainter, QFont from PyQt5 import QtGui import os import sys import cv2 import math class mainwindow(QWidget): def __init__(self): super().__init__() self.top = 200 self.left = 500 self.width = 700 self.height = 700 self.imageheight = 600 self.imagewidth = 600 self.setWindowTitle("face tagging") self.setGeometry(self.left, self.top, self.width, self.height) self.label = QLabel("image presented here ", self) self.label.move(200, 200) self.btn2 = QPushButton("image editor", self) self.btn2.clicked.connect(self.editing_window) self.btn3 = QPushButton("Locate face", self) self.btn3.clicked.connect(self.findFace) self.btn4 = QPushButton("delete faces", self) self.btn4.clicked.connect(self.delete_false_face) self.btn5 = QPushButton("add faces", self) self.btn6 = QPushButton("name tag", self) self.btn6.clicked.connect(self.createtagwindow) self.btn5.clicked.connect(self.enabled) self.imagepath = "" self.fList = facelist() self.delclick = False self.enable = False # QPixmap to draw on self.pix = QtGui.QPixmap(self.imagepath) self.begin = QPoint() self.destination = QPoint() vbox = QHBoxLayout() vbox.addWidget(self.btn2) vbox.addWidget(self.btn3) vbox.addWidget(self.btn4) vbox.addWidget(self.btn5) buttons_widget = QWidget() buttons_widget.setLayout(vbox) hbox = QHBoxLayout() hbox.addWidget(self.label) hbox.addWidget(buttons_widget) self.setLayout(hbox) self.setwidget() def setwidget(self): self.btn1 = QPushButton("upload here", self) self.btn1.clicked.connect(self.obtainphoto) def editing_window(self): self.editwin = createwindow(self) self.editwin.show() def obtainphoto(self): fname = QFileDialog.getOpenFileName(self, "open file") self.imagepath = fname[0] self.originalpath = fname[0] self.renderimage() def renderimage(self): self.pixmap = QPixmap(self.imagepath) self.pixmap_resized = self.pixmap.scaled( self.imagewidth, self.imageheight, Qt.KeepAspectRatio, Qt.SmoothTransformation, ) self.label.setPixmap(self.pixmap_resized) self.pix = QtGui.QPixmap(self.pixmap_resized) def display_image(self, img): height, width, colors = img.shape bytesperline = 3 * width image = QImage(img.data, width, height, bytesperline, QImage.Format_RGB888) self.image = image.rgbSwapped() self.label.setPixmap(QPixmap.fromImage(self.image)) def findFace(self): face_cascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml") img = cv2.imread(self.imagepath, cv2.IMREAD_COLOR) img = cv2.resize(img, (self.imagewidth, self.imageheight)) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) faces = face_cascade.detectMultiScale(gray, 2, 1).tolist() for x, y, w, h in faces: self.fList.append_face(x, y, w, h) cv2.rectangle(img, (x, y), (x + w, y + h), (255, 255, 0), 2) self.display_image(img) def createtagwindow(self): self.tagwin = tagwindow() self.tagwin.setwidgets(self) self.tagwin.show() def delete_false_face(self): if self.label.pixmap() is None: print("Photo is not present within the given area") elif self.fList is None or self.fList.count_face() == 0: print("No face is detected") else: print("Which face do you want to delete?") self.delclick = True def createaddfacewin(self): self.addfacewin = addfacewindow(self) self.addfacewin.setwidgets(self) self.addfacewin.show() def mousePressEvent(self, event): if event.buttons() & Qt.LeftButton and self.enable: self.begin = event.pos() self.destination = self.begin self.update() def mouseMoveEvent(self, event): if event.buttons() & Qt.LeftButton and self.enable: self.destination = event.pos() self.update() def mouseReleaseEvent(self, event): if event.button() & Qt.LeftButton and self.enable: rect = self.get_rect_from_center(self.begin, self.destination) painter = QPainter(self.pix) painter.setPen(QPen(QColor("blue"), 3)) painter.drawRect(rect.normalized()) self.fList.append_face(rect.x(), rect.y(), rect.width(), rect.height()) self.begin, self.destination = QPoint(), QPoint() self.update() def paintEvent(self, event): painter = QPainter(self) if self.pix: painter.drawPixmap(0, 0, self.pix) if not self.begin.isNull() and not self.destination.isNull() and self.enable: painter.setPen(QPen(QColor("blue"), 3)) rect = self.get_rect_from_center(self.begin, self.destination) painter.drawRect(rect.normalized()) def get_rect_from_center(self, center, edge): width = abs(edge.x() - center.x()) * 2 height = abs(edge.y() - center.y()) * 2 top_left = QPoint(center.x() - width // 2, center.y() - height // 2) bottom_right = QPoint(center.x() + width // 2, center.y() + height // 2) return QRect(top_left, bottom_right) def enabled(self): self.enable = True class createwindow(QWidget): def __init__(self, mainwindow_instance): super().__init__() self.mainwindow_instance = mainwindow_instance self.width = 350 self.height = 350 self.setWindowTitle("Image Editor") self.setGeometry(500, 200, self.width, self.height) self.setwidget() def setwidget(self): self.labelwidth = QLabel("width editor", self) self.labelwidth.move(20, 20) self.textwidth = QLineEdit("width", self) self.textwidth.move(20, 50) self.labelheight = QLabel("height editor", self) self.labelheight.move(20, 100) self.textheight = QLineEdit("height", self) self.textheight.move(20, 130) self.labelcolor = QLabel("adjust photo color", self) self.labelcolor.move(20, 180) self.radiobtn1 = QRadioButton("original", self) self.radiobtn1.setChecked(True) self.radiobtn1.move(20, 210) self.radiochecked = "original" self.radiobtn2 = QRadioButton("grey", self) self.radiobtn2.move(20, 240) self.radiobtn3 = QRadioButton("red", self) self.radiobtn3.move(20, 270) self.radiobtn4 = QRadioButton("green", self) self.radiobtn4.move(20, 300) self.radiobtn5 = QRadioButton("blue", self) self.radiobtn5.move(20, 330) self.radiobtn6 = QRadioButton("turquoise", self) self.radiobtn6.move(90, 210) self.radiobtn7 = QRadioButton("orange", self) self.radiobtn7.move(90, 240) self.btn_confirm = QPushButton("confirm changes", self) self.btn_confirm.move(230, 20) self.btn_confirm.clicked.connect(self.editimage) self.radiobtn1.toggled.connect(self.btnstate) self.radiobtn2.toggled.connect(self.btnstate) self.radiobtn3.toggled.connect(self.btnstate) self.radiobtn4.toggled.connect(self.btnstate) self.radiobtn5.toggled.connect(self.btnstate) self.radiobtn6.toggled.connect(self.btnstate) self.radiobtn7.toggled.connect(self.btnstate) def btnstate(self): radiobtn = self.sender() self.radiochecked = radiobtn.text() def editimage(self): img = Image.open(self.mainwindow_instance.originalpath) img = img.convert("RGB") if self.radiochecked == "original": img_edited = img elif self.radiochecked == "grey": img_edited = img.convert("L") elif self.radiochecked == "red": red = ( 0.90, 0.36, 0.18, 0.00, 0.11, 0.72, 0.07, 0.00, 0.02, 0.12, 0.95, 0.00, ) img_edited = img.convert("RGB", red) elif self.radiochecked == "blue": blue = ( 0.18, 0.36, 0.90, 0.00, 0.07, 0.72, 0.11, 0.00, 0.95, 0.12, 0.02, 0.00, ) img_edited = img.convert("RGB", blue) elif self.radiochecked == "green": green = ( 0.18, 0.90, 0.36, 0.00, 0.07, 0.11, 0.72, 0.00, 0.95, 0.02, 0.12, 0.00, ) img_edited = img.convert("RGB", green) elif self.radiochecked == "turquoise": turquoise = ( 0.18, 0.36, 0.90, 0.00, 0.72, 0.11, 0.07, 0.00, 0.12, 0.02, 0.95, 0.00, ) img_edited = img.convert("RGB", turquoise) elif self.radiochecked == "orange": orange = ( 0.95, 0.02, 0.12, 0.00, 0.11, 0.72, 0.07, 0.00, 0.18, 0.36, 0.90, 0.00, ) img_edited = img.convert("RGB", orange) if img_edited.mode == "RGBA": img_edited = img_edited.convert("RGB") img_edited.save("image_edited.jpg", "JPEG") self.mainwindow_instance.imagepath = os.path.join( os.getcwd(), "image_edited.jpg" ) try: imgwidth_edited = self.textwidth.text() imgheight_edited = self.textheight.text() if imgwidth_edited == "width": imgwidth_edited = str(self.mainwindow_instance.imagewidth) if imgheight_edited == "height": imgheight_edited = str(self.mainwindow_instance.imageheight) self.mainwindow_instance.imagewidth = int(imgwidth_edited) self.mainwindow_instance.imageheight = int(imgheight_edited) self.mainwindow_instance.renderimage() self.close() except ValueError: QMessageBox.warning( self, "Invalid Input", "Please enter valid integer values for width and height.", ) class addfacewindow(QWidget): def __init__(self, mainwindow): super().__init__() def setwidgets(self, mainwindow): self.setGeometry(mainwindow.left, mainwindow.top, 200, 300) self.mlabel = squarelabel( mainwindow.imagepath, mainwindow.imagewidth, mainwindow.imageheight, mainwindow.fList, ) self.pixmap = QPixmap(mainwindow.imagepath) self.pixmap_resized = self.pixmap.scaled( mainwindow.imagewidth, mainwindow.imageheight ) self.mlabel.setPixmap(self.pixmap_resized) self.addface = QPushButton("add face", self) self.addface.clicked.connect(lambda: self.mlabel.addface()) self.btnconfirm = QPushButton("confirm", self) vbox = QVBoxLayout() vbox.addWidget(self.addface) vbox.addWidget(self.btnconfirm) widgetbutton = QWidget() widgetbutton.setLayout(vbox) hbox = QHBoxLayout() hbox.addWidget(self.mlabel) hbox.addWidget(widgetbutton) self.setLayout(hbox) class tagwindow(mainwindow): def __init__(self): super().__init__() def setwidgets(self, mainwindow): self.setGeometry(self.left, self.top, 200, 300) self.mlabel = taglabel( mainwindow.imagepath, mainwindow.width, mainwindow.height, mainwindow.fList ) self.btnSave = QPushButton("store this", self) self.btnSave.clicked.connect(lambda: self.mlabel.saveFile()) self.btnOK = QPushButton("confirm", self) self.btnOK.clicked.connect(lambda: self.finishTag(mainwindow)) vbox = QVBoxLayout() vbox.addWidget(self.btnSave) vbox.addWidget(self.btnOK) button_widget = QWidget() button_widget.setLayout(vbox) hbox = QHBoxLayout() hbox.addWidget(self.mlabel) hbox.addWidget(button_widget) self.setLayout(hbox) class squarelabel(QLabel): def __init__(self, imgpath, w, h, facelist): super().__init__() self.pixmap = QPixmap(imgpath) self.pixmap_resized = self.pixmap.scaled(w, h) self.setPixmap(self.pixmap_resized) painter = QPainter(self.pixmap_resized) painter.setPen(QPen(QColor("blue"), 3)) self.facelist = facelist for f in self.facelist.face_list: print(f.x, f.y, f.w, f.h) painter.drawRect(f.x, f.y, f.w, f.h) self.setPixmap(self.pixmap_resized) self.left_clicking = False def mousepressevent(self, event): if event.button() == 1: self.startX = event.x() self.starty = event.y() self.left_clicking = True def mouserelease(self, event): if event.button() == 1: self.finishX = event.x() self.finishY = event.y() self.left_clicking = False def mousemovement(self, event): if self.left_clicking: self.pixmap_temp = self.pixmap_resized.copy() painter = QPainter(self.pixmap_temp) painter.setPen(QPen(QColor("green"), 3)) painter.drawRect( self.startX, self.startY, event.x() - self.startX, event.y() - self.startY, ) self.setPixmap(self.pixmap_temp) def addface(self): x, y, w, h = ( self.startX, self.startY, self.finishX - self.startX, self.finishY - self.startY, ) self.facelist.append_face(x, y, w, h) painter = QPainter(self.pixmap_temp) painter.setPen(QPen(QColor("blue"), 3)) painter.drawRect(x, y, w, h) self.setPixmap(self.pixmap_resized) def finishface(self, mainwindow): mainwindow.label.setPixmap(self.mlabel.pixmap_resized) self.close() class taglabel(squarelabel): def __init__(self, imgpath, w, h, facelist): super().__init__(imgpath, w, h, facelist) def mousepress(self, event): for f in self.facelist.face_list: if f.x <= event.x() <= f.x + f.w and f.y <= event.y() <= f.y + f.h: print("face Id", f.id, f.name) text, pressconfirm = QInputDialog.getText( self, "input", "name:", QLineEdit.Normal ) if pressconfirm and text != "": f.name = text break self.drawnames() def drawnames(self): self.pixmap_temp = self.pixmap_resized.copy() painter = QPainter(self.pixmap_temp) painter.setPen(QPen(QColor("blue"), 3)) for f in self.facelist.face_list: painter.drawText(f.x, f.y - 5, f.name) painter.end() self.setPixmap(self.pixmap_temp) def saveFile(self): text, confirmpress = QInputDialog.getText( self, "file name inputter", "file name", QLineEdit.Normal ) if confirmpress: self.pixmap_temp.save(text + "jpg", "JPG") def finishTag(self, mainwindow): mainwindow.label.setPixmap(self.mlabel.pixmap_temp) self.close() def mouserelease(self, event): pass def mousemove(self, event): pass class facelist: def __init__(self): self.face_list = [] self.face_id = 0 def append_face(self, x, y, w, h, name=None): face = Face(self.face_id, x, y, w, h, name) self.face_list.append(face) self.face_id += 1 def remove_face(self, face_id): for face in self.face_list: if face.id == face_id: self.face_list.remove(face) break def count_face(self): return len(self.face_list) class Face: def __init__(self, face_id, x, y, w, h, name=None): self.id = face_id self.x = x self.y = y self.w = w self.h = h self.name = name if __name__ == '__main__': app = QApplication(sys.argv) mainwin = mainwindow() mainwin.show() sys.exit(app.exec_()) </code>
from PyQt5.QtGui import QMouseEvent, QPixmap, QImage, QPainter, QPen, QColor
from PyQt5.QtWidgets import (
    QApplication,
    QWidget,
    QPushButton,
    QLabel,
    QVBoxLayout,
    QHBoxLayout,
    QFileDialog,
    QLineEdit,
    QRadioButton,
    QMessageBox,
    QInputDialog,
)
from PIL import Image, ImageEnhance, ImageColor
from PyQt5.QtCore import Qt, QPoint, QRect
from PyQt5.QtGui import QPixmap, QPainter, QFont
from PyQt5 import QtGui
import os
import sys
import cv2
import math


class mainwindow(QWidget):
    def __init__(self):
        super().__init__()
        self.top = 200
        self.left = 500
        self.width = 700
        self.height = 700
        self.imageheight = 600
        self.imagewidth = 600
        self.setWindowTitle("face tagging")
        self.setGeometry(self.left, self.top, self.width, self.height)
        self.label = QLabel("image presented here ", self)
        self.label.move(200, 200)
        self.btn2 = QPushButton("image editor", self)
        self.btn2.clicked.connect(self.editing_window)

        self.btn3 = QPushButton("Locate face", self)
        self.btn3.clicked.connect(self.findFace)

        self.btn4 = QPushButton("delete faces", self)
        self.btn4.clicked.connect(self.delete_false_face)
        self.btn5 = QPushButton("add faces", self)
        self.btn6 = QPushButton("name tag", self)
        self.btn6.clicked.connect(self.createtagwindow)
        self.btn5.clicked.connect(self.enabled)
        self.imagepath = ""

        self.fList = facelist()
        self.delclick = False
        self.enable = False
        # QPixmap to draw on
        self.pix = QtGui.QPixmap(self.imagepath)

        self.begin = QPoint()
        self.destination = QPoint()

        vbox = QHBoxLayout()
        vbox.addWidget(self.btn2)
        vbox.addWidget(self.btn3)
        vbox.addWidget(self.btn4)
        vbox.addWidget(self.btn5)
        buttons_widget = QWidget()
        buttons_widget.setLayout(vbox)
        hbox = QHBoxLayout()
        hbox.addWidget(self.label)
        hbox.addWidget(buttons_widget)
        self.setLayout(hbox)
        self.setwidget()

    def setwidget(self):
        self.btn1 = QPushButton("upload here", self)
        self.btn1.clicked.connect(self.obtainphoto)

    def editing_window(self):
        self.editwin = createwindow(self)
        self.editwin.show()

    def obtainphoto(self):
        fname = QFileDialog.getOpenFileName(self, "open file")
        self.imagepath = fname[0]
        self.originalpath = fname[0]
        self.renderimage()

    def renderimage(self):
        self.pixmap = QPixmap(self.imagepath)
        self.pixmap_resized = self.pixmap.scaled(
            self.imagewidth,
            self.imageheight,
            Qt.KeepAspectRatio,
            Qt.SmoothTransformation,
        )
        self.label.setPixmap(self.pixmap_resized)
        self.pix = QtGui.QPixmap(self.pixmap_resized)

    def display_image(self, img):
        height, width, colors = img.shape
        bytesperline = 3 * width
        image = QImage(img.data, width, height, bytesperline, QImage.Format_RGB888)
        self.image = image.rgbSwapped()
        self.label.setPixmap(QPixmap.fromImage(self.image))

    def findFace(self):
        face_cascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
        img = cv2.imread(self.imagepath, cv2.IMREAD_COLOR)
        img = cv2.resize(img, (self.imagewidth, self.imageheight))

        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        faces = face_cascade.detectMultiScale(gray, 2, 1).tolist()
        for x, y, w, h in faces:
            self.fList.append_face(x, y, w, h)
            cv2.rectangle(img, (x, y), (x + w, y + h), (255, 255, 0), 2)
        self.display_image(img)

    def createtagwindow(self):
        self.tagwin = tagwindow()
        self.tagwin.setwidgets(self)
        self.tagwin.show()

    def delete_false_face(self):
        if self.label.pixmap() is None:
            print("Photo is not present within the given area")
        elif self.fList is None or self.fList.count_face() == 0:
            print("No face is detected")
        else:
            print("Which face do you want to delete?")
            self.delclick = True

    def createaddfacewin(self):
        self.addfacewin = addfacewindow(self)
        self.addfacewin.setwidgets(self)
        self.addfacewin.show()

    def mousePressEvent(self, event):
        if event.buttons() & Qt.LeftButton and self.enable:
            self.begin = event.pos()
            self.destination = self.begin
            self.update()

    def mouseMoveEvent(self, event):
        if event.buttons() & Qt.LeftButton and self.enable:
            self.destination = event.pos()
            self.update()

    def mouseReleaseEvent(self, event):
        if event.button() & Qt.LeftButton and self.enable:
            rect = self.get_rect_from_center(self.begin, self.destination)
            painter = QPainter(self.pix)
            painter.setPen(QPen(QColor("blue"), 3))
            painter.drawRect(rect.normalized())
            self.fList.append_face(rect.x(), rect.y(), rect.width(), rect.height())
            self.begin, self.destination = QPoint(), QPoint()
            self.update()

    def paintEvent(self, event):
        painter = QPainter(self)
        if self.pix:
            painter.drawPixmap(0, 0, self.pix)
        if not self.begin.isNull() and not self.destination.isNull() and self.enable:
            painter.setPen(QPen(QColor("blue"), 3))
            rect = self.get_rect_from_center(self.begin, self.destination)
            painter.drawRect(rect.normalized())

    def get_rect_from_center(self, center, edge):
        width = abs(edge.x() - center.x()) * 2
        height = abs(edge.y() - center.y()) * 2
        top_left = QPoint(center.x() - width // 2, center.y() - height // 2)
        bottom_right = QPoint(center.x() + width // 2, center.y() + height // 2)
        return QRect(top_left, bottom_right)

    def enabled(self):
        self.enable = True


class createwindow(QWidget):
    def __init__(self, mainwindow_instance):
        super().__init__()
        self.mainwindow_instance = mainwindow_instance
        self.width = 350
        self.height = 350
        self.setWindowTitle("Image Editor")
        self.setGeometry(500, 200, self.width, self.height)
        self.setwidget()

    def setwidget(self):
        self.labelwidth = QLabel("width editor", self)
        self.labelwidth.move(20, 20)
        self.textwidth = QLineEdit("width", self)
        self.textwidth.move(20, 50)
        self.labelheight = QLabel("height editor", self)
        self.labelheight.move(20, 100)
        self.textheight = QLineEdit("height", self)
        self.textheight.move(20, 130)
        self.labelcolor = QLabel("adjust photo color", self)
        self.labelcolor.move(20, 180)
        self.radiobtn1 = QRadioButton("original", self)
        self.radiobtn1.setChecked(True)
        self.radiobtn1.move(20, 210)
        self.radiochecked = "original"
        self.radiobtn2 = QRadioButton("grey", self)
        self.radiobtn2.move(20, 240)
        self.radiobtn3 = QRadioButton("red", self)
        self.radiobtn3.move(20, 270)
        self.radiobtn4 = QRadioButton("green", self)
        self.radiobtn4.move(20, 300)
        self.radiobtn5 = QRadioButton("blue", self)
        self.radiobtn5.move(20, 330)
        self.radiobtn6 = QRadioButton("turquoise", self)
        self.radiobtn6.move(90, 210)
        self.radiobtn7 = QRadioButton("orange", self)
        self.radiobtn7.move(90, 240)
        self.btn_confirm = QPushButton("confirm changes", self)
        self.btn_confirm.move(230, 20)
        self.btn_confirm.clicked.connect(self.editimage)
        self.radiobtn1.toggled.connect(self.btnstate)
        self.radiobtn2.toggled.connect(self.btnstate)
        self.radiobtn3.toggled.connect(self.btnstate)
        self.radiobtn4.toggled.connect(self.btnstate)
        self.radiobtn5.toggled.connect(self.btnstate)
        self.radiobtn6.toggled.connect(self.btnstate)
        self.radiobtn7.toggled.connect(self.btnstate)

    def btnstate(self):
        radiobtn = self.sender()
        self.radiochecked = radiobtn.text()

    def editimage(self):
        img = Image.open(self.mainwindow_instance.originalpath)
        img = img.convert("RGB")
        if self.radiochecked == "original":
            img_edited = img
        elif self.radiochecked == "grey":
            img_edited = img.convert("L")
        elif self.radiochecked == "red":
            red = (
                0.90,
                0.36,
                0.18,
                0.00,
                0.11,
                0.72,
                0.07,
                0.00,
                0.02,
                0.12,
                0.95,
                0.00,
            )
            img_edited = img.convert("RGB", red)
        elif self.radiochecked == "blue":
            blue = (
                0.18,
                0.36,
                0.90,
                0.00,
                0.07,
                0.72,
                0.11,
                0.00,
                0.95,
                0.12,
                0.02,
                0.00,
            )
            img_edited = img.convert("RGB", blue)
        elif self.radiochecked == "green":
            green = (
                0.18,
                0.90,
                0.36,
                0.00,
                0.07,
                0.11,
                0.72,
                0.00,
                0.95,
                0.02,
                0.12,
                0.00,
            )
            img_edited = img.convert("RGB", green)
        elif self.radiochecked == "turquoise":
            turquoise = (
                0.18,
                0.36,
                0.90,
                0.00,
                0.72,
                0.11,
                0.07,
                0.00,
                0.12,
                0.02,
                0.95,
                0.00,
            )
            img_edited = img.convert("RGB", turquoise)
        elif self.radiochecked == "orange":
            orange = (
                0.95,
                0.02,
                0.12,
                0.00,
                0.11,
                0.72,
                0.07,
                0.00,
                0.18,
                0.36,
                0.90,
                0.00,
            )
            img_edited = img.convert("RGB", orange)

        if img_edited.mode == "RGBA":
            img_edited = img_edited.convert("RGB")

        img_edited.save("image_edited.jpg", "JPEG")
        self.mainwindow_instance.imagepath = os.path.join(
            os.getcwd(), "image_edited.jpg"
        )
        try:
            imgwidth_edited = self.textwidth.text()
            imgheight_edited = self.textheight.text()
            if imgwidth_edited == "width":
                imgwidth_edited = str(self.mainwindow_instance.imagewidth)
            if imgheight_edited == "height":
                imgheight_edited = str(self.mainwindow_instance.imageheight)
            self.mainwindow_instance.imagewidth = int(imgwidth_edited)
            self.mainwindow_instance.imageheight = int(imgheight_edited)
            self.mainwindow_instance.renderimage()
            self.close()
        except ValueError:
            QMessageBox.warning(
                self,
                "Invalid Input",
                "Please enter valid integer values for width and height.",
            )


class addfacewindow(QWidget):
    def __init__(self, mainwindow):
        super().__init__()

    def setwidgets(self, mainwindow):
        self.setGeometry(mainwindow.left, mainwindow.top, 200, 300)
        self.mlabel = squarelabel(
            mainwindow.imagepath,
            mainwindow.imagewidth,
            mainwindow.imageheight,
            mainwindow.fList,
        )
        self.pixmap = QPixmap(mainwindow.imagepath)
        self.pixmap_resized = self.pixmap.scaled(
            mainwindow.imagewidth, mainwindow.imageheight
        )
        self.mlabel.setPixmap(self.pixmap_resized)

        self.addface = QPushButton("add face", self)
        self.addface.clicked.connect(lambda: self.mlabel.addface())

        self.btnconfirm = QPushButton("confirm", self)

        vbox = QVBoxLayout()
        vbox.addWidget(self.addface)
        vbox.addWidget(self.btnconfirm)
        widgetbutton = QWidget()
        widgetbutton.setLayout(vbox)

        hbox = QHBoxLayout()
        hbox.addWidget(self.mlabel)
        hbox.addWidget(widgetbutton)
        self.setLayout(hbox)


class tagwindow(mainwindow):
    def __init__(self):
        super().__init__()

    def setwidgets(self, mainwindow):
        self.setGeometry(self.left, self.top, 200, 300)

        self.mlabel = taglabel(
            mainwindow.imagepath, mainwindow.width, mainwindow.height, mainwindow.fList
        )
        self.btnSave = QPushButton("store this", self)
        self.btnSave.clicked.connect(lambda: self.mlabel.saveFile())
        self.btnOK = QPushButton("confirm", self)
        self.btnOK.clicked.connect(lambda: self.finishTag(mainwindow))

        vbox = QVBoxLayout()
        vbox.addWidget(self.btnSave)
        vbox.addWidget(self.btnOK)

        button_widget = QWidget()
        button_widget.setLayout(vbox)

        hbox = QHBoxLayout()
        hbox.addWidget(self.mlabel)
        hbox.addWidget(button_widget)
        self.setLayout(hbox)


class squarelabel(QLabel):
    def __init__(self, imgpath, w, h, facelist):
        super().__init__()
        self.pixmap = QPixmap(imgpath)
        self.pixmap_resized = self.pixmap.scaled(w, h)
        self.setPixmap(self.pixmap_resized)

        painter = QPainter(self.pixmap_resized)
        painter.setPen(QPen(QColor("blue"), 3))

        self.facelist = facelist
        for f in self.facelist.face_list:
            print(f.x, f.y, f.w, f.h)
            painter.drawRect(f.x, f.y, f.w, f.h)

        self.setPixmap(self.pixmap_resized)
        self.left_clicking = False

    def mousepressevent(self, event):
        if event.button() == 1:
            self.startX = event.x()
            self.starty = event.y()
            self.left_clicking = True

    def mouserelease(self, event):
        if event.button() == 1:
            self.finishX = event.x()
            self.finishY = event.y()
            self.left_clicking = False

    def mousemovement(self, event):
        if self.left_clicking:
            self.pixmap_temp = self.pixmap_resized.copy()
            painter = QPainter(self.pixmap_temp)
            painter.setPen(QPen(QColor("green"), 3))
            painter.drawRect(
                self.startX,
                self.startY,
                event.x() - self.startX,
                event.y() - self.startY,
            )
            self.setPixmap(self.pixmap_temp)

    def addface(self):
        x, y, w, h = (
            self.startX,
            self.startY,
            self.finishX - self.startX,
            self.finishY - self.startY,
        )
        self.facelist.append_face(x, y, w, h)
        painter = QPainter(self.pixmap_temp)
        painter.setPen(QPen(QColor("blue"), 3))
        painter.drawRect(x, y, w, h)
        self.setPixmap(self.pixmap_resized)

    def finishface(self, mainwindow):
        mainwindow.label.setPixmap(self.mlabel.pixmap_resized)
        self.close()


class taglabel(squarelabel):
    def __init__(self, imgpath, w, h, facelist):
        super().__init__(imgpath, w, h, facelist)

    def mousepress(self, event):
        for f in self.facelist.face_list:
            if f.x <= event.x() <= f.x + f.w and f.y <= event.y() <= f.y + f.h:
                print("face Id", f.id, f.name)
                text, pressconfirm = QInputDialog.getText(
                    self, "input", "name:", QLineEdit.Normal
                )
                if pressconfirm and text != "":
                    f.name = text
                break
        self.drawnames()

    def drawnames(self):
        self.pixmap_temp = self.pixmap_resized.copy()
        painter = QPainter(self.pixmap_temp)
        painter.setPen(QPen(QColor("blue"), 3))
        for f in self.facelist.face_list:
            painter.drawText(f.x, f.y - 5, f.name)
        painter.end()
        self.setPixmap(self.pixmap_temp)

    def saveFile(self):
        text, confirmpress = QInputDialog.getText(
            self, "file name inputter", "file name", QLineEdit.Normal
        )
        if confirmpress:
            self.pixmap_temp.save(text + "jpg", "JPG")

    def finishTag(self, mainwindow):
        mainwindow.label.setPixmap(self.mlabel.pixmap_temp)
        self.close()

    def mouserelease(self, event):
        pass

    def mousemove(self, event):
        pass


class facelist:
    def __init__(self):
        self.face_list = []
        self.face_id = 0

    def append_face(self, x, y, w, h, name=None):
        face = Face(self.face_id, x, y, w, h, name)
        self.face_list.append(face)
        self.face_id += 1

    def remove_face(self, face_id):
        for face in self.face_list:
            if face.id == face_id:
                self.face_list.remove(face)
                break

    def count_face(self):
        return len(self.face_list)


class Face:
    def __init__(self, face_id, x, y, w, h, name=None):
        self.id = face_id
        self.x = x
        self.y = y
        self.w = w
        self.h = h
        self.name = name


if __name__ == '__main__':
    app = QApplication(sys.argv)
    mainwin = mainwindow()
    mainwin.show()
    sys.exit(app.exec_())

after pressing the “upload image ” button, i expected a singular image which i could discover, add, and remove faces from. However, what ended up occuring were two overlapping images, with one being able to have the faces removed and the other one being able to have faces added.

Dark blue square denotes how the faces are to be drawn.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật