Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

增加可选功能 扁平化选区 若启用则支持选区增减交异或 (有事,故懒得改了) #169

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
增加可选功能 扁平化选区 若启用则支持选区增减交异或
  • Loading branch information
XieDeWu committed Jun 1, 2024
commit 9d0756c4fb37353a9448aea36ceb5b2efb12599b
20 changes: 20 additions & 0 deletions ISAT/ui/MainWindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,13 @@ def setupUi(self, MainWindow):
self.menuMode.setObjectName("menuMode")
self.menuContour_mode = QtWidgets.QMenu(self.menuMode)
self.menuContour_mode.setObjectName("menuContour_mode")
self.menuFlatten_selection = QtWidgets.QAction(self.menuMode)
self.menuFlatten_selection.setCheckable(True)
font = QtGui.QFont()
font.setFamily("Times New Roman")
font.setPointSize(12)
self.menuFlatten_selection.setFont(font)
self.menuFlatten_selection.setObjectName("menuFlatten_selection")
self.menuSAM_model = QtWidgets.QMenu(self.menubar)
self.menuSAM_model.setObjectName("menuSAM_model")
MainWindow.setMenuBar(self.menubar)
Expand Down Expand Up @@ -256,6 +263,9 @@ def setupUi(self, MainWindow):
self.actionCancel.setIcon(icon20)
self.actionCancel.setObjectName("actionCancel")
self.actionFinish = QtWidgets.QAction(MainWindow)
self.actionFinishShift = QtWidgets.QAction(MainWindow)
self.actionFinishAlt = QtWidgets.QAction(MainWindow)
self.actionFinishShiftAlt = QtWidgets.QAction(MainWindow)
icon21 = QtGui.QIcon()
icon21.addPixmap(QtGui.QPixmap(":/icon/icons/校验_check-one.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.actionFinish.setIcon(icon21)
Expand Down Expand Up @@ -338,6 +348,9 @@ def setupUi(self, MainWindow):
self.menuEdit.addAction(self.actionPolygon)
self.menuEdit.addAction(self.actionBackspace)
self.menuEdit.addAction(self.actionFinish)
self.menuEdit.addAction(self.actionFinishShift)
self.menuEdit.addAction(self.actionFinishAlt)
self.menuEdit.addAction(self.actionFinishShiftAlt)
self.menuEdit.addAction(self.actionCancel)
self.menuEdit.addSeparator()
self.menuEdit.addAction(self.actionTo_top)
Expand All @@ -350,6 +363,7 @@ def setupUi(self, MainWindow):
self.menuContour_mode.addAction(self.actionContour_External)
self.menuContour_mode.addAction(self.actionContour_All)
self.menuMode.addAction(self.menuContour_mode.menuAction())
self.menuMode.addAction(self.menuFlatten_selection)
self.menuSAM_model.addAction(self.actionModel_manage)
self.menuSAM_model.addSeparator()
self.menubar.addAction(self.menuFile.menuAction())
Expand Down Expand Up @@ -395,6 +409,9 @@ def retranslateUi(self, MainWindow):
self.menuEdit.setTitle(_translate("MainWindow", "Edit"))
self.menuMode.setTitle(_translate("MainWindow", "Mode"))
self.menuContour_mode.setTitle(_translate("MainWindow", "Contour mode"))
self.menuFlatten_selection.setText(_translate("MainWindow", "Flatten selection"))
self.menuFlatten_selection.setStatusTip(_translate("MainWindow", "Flatten selection tips"))
self.menuFlatten_selection.setWhatsThis(_translate("MainWindow", "Flatten selection tips"))
self.menuSAM_model.setTitle(_translate("MainWindow", "SAM"))
self.toolBar.setWindowTitle(_translate("MainWindow", "toolBar"))
self.info_dock.setWindowTitle(_translate("MainWindow", "Info"))
Expand Down Expand Up @@ -467,6 +484,9 @@ def retranslateUi(self, MainWindow):
self.actionFinish.setToolTip(_translate("MainWindow", "Annotate finished"))
self.actionFinish.setStatusTip(_translate("MainWindow", "Annotate finished."))
self.actionFinish.setShortcut(_translate("MainWindow", "E"))
self.actionFinishShift.setShortcut(_translate("MainWindow", "Shift+E"))
self.actionFinishAlt.setShortcut(_translate("MainWindow", "Alt+E"))
self.actionFinishShiftAlt.setShortcut(_translate("MainWindow", "Shift+Alt+E"))
self.actionPolygon.setText(_translate("MainWindow", "Polygon"))
self.actionPolygon.setToolTip(_translate("MainWindow", "Draw polygon"))
self.actionPolygon.setStatusTip(_translate("MainWindow", "Accurately annotate by drawing polygon. "))
Expand Down
10 changes: 10 additions & 0 deletions ISAT/ui/zh_CN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1414,6 +1414,16 @@
<source>Contour mode</source>
<translation>轮廓模式</translation>
</message>
<message>
<location filename="MainWindow.py" line="403"/>
<source>Flatten selection</source>
<translation>扁平化选区</translation>
</message>
<message>
<location filename="MainWindow.py" line="404"/>
<source>Flatten selection tips</source>
<translation>在完成选区时,默认求并,按Shift求减,按Alt求交,按Shift+Alt求异或</translation>
</message>
<message>
<location filename="MainWindow.py" line="395"/>
<source>SAM</source>
Expand Down
65 changes: 64 additions & 1 deletion ISAT/widgets/canvas.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
# -*- coding: utf-8 -*-
# @Author : LG

from itertools import chain
from PyQt5 import QtWidgets, QtGui, QtCore
import shapely.ops
from ISAT.widgets.polygon import Polygon, Vertex, PromptPoint, Line
from ISAT.configs import STATUSMode, CLICKMode, DRAWMode, CONTOURMode
from PIL import Image
import numpy as np
import cv2
import time # 拖动鼠标描点
import keyboard
import shapely
from shapely.geometry import Polygon as PO,MultiPolygon


class AnnotationScene(QtWidgets.QGraphicsScene):
Expand Down Expand Up @@ -235,7 +240,8 @@ def finish_draw(self):
group = self.mainwindow.current_group
is_crowd = False
note = ''

# 计算用临时变量
oldPolygonCount = len(self.mainwindow.polygons)
if self.draw_mode == DRAWMode.SEGMENTANYTHING:
# mask to polygon
# --------------
Expand Down Expand Up @@ -338,6 +344,63 @@ def finish_draw(self):
self.current_graph.setZValue(len(self.mainwindow.polygons))
for vertex in self.current_graph.vertexs:
vertex.setZValue(len(self.mainwindow.polygons))

# 若启用扁平化选区,则可进行选区交互: 并(默认),减(Shift),交(Alt),异或(Shift+Alt)
# 仅针对同标签选区进行扁平化
# 核心是使用Shapely库进行区域处理
if self.isFlattenSelection :
shift = keyboard.is_pressed("Shift")
alt = keyboard.is_pressed("Alt")
secToShapely = lambda it:list(map(lambda it: PO((lambda x: [] if len(x)<3 else x )(list(map(lambda it:[it.x(),it.y()],it.points)))),it))
# 对同标签选区,注意 我在前文中加了个临时变量 oldPolygonCount
add_count = len(self.mainwindow.polygons) - oldPolygonCount
sec = list(it for it in self.mainwindow.polygons if it.category == category)
sec_old = sec[0:-add_count]
sec_new = sec[-add_count:]
secOldShapely = secToShapely(sec_old)
secNewShapely = secToShapely(sec_new)
# 移除旧多边形
for polygon in sec :
polygons = self.mainwindow.polygons
if polygon in polygons:
polygons.remove(polygon)
polygon.delete()
if polygon in self.items():
self.removeItem(polygon)
del polygon
# 计算合并区域
old: MultiPolygon = MultiPolygon(secOldShapely).buffer(0)
new: MultiPolygon = MultiPolygon(secNewShapely).buffer(0)
union : MultiPolygon = new
if not old.is_empty and not new.is_empty :
# 增
if not shift and not alt :
union = old.union(new)
# 减
if shift and not alt :
union = old.difference(new)
# 交
if not shift and alt :
union = old.intersection(new)
# 异或
if shift and alt :
union = old.symmetric_difference(new)
# 添加处理结果
geoms = [union] if isinstance(union, PO) else list(union.geoms) if isinstance(union, MultiPolygon) else [union]
geoms = [it for it in geoms if not it.is_empty and it.is_valid and isinstance(it,PO)]
for geo in geoms :
merge = Polygon()
self.addItem(merge) #先挂载其上下文,Polygon内部函数均建立在已挂载的前提上
ring = list(chain.from_iterable(map(lambda it:zip(it[::2],it[1::2]),geo.exterior.coords._coords)))
list(map(lambda it: merge.addPoint(QtCore.QPointF(it[0], it[1])),ring))
merge.set_drawed(category,
group,
is_crowd,
note,
QtGui.QColor(self.mainwindow.category_color_dict[category]),
self.top_layer)
self.mainwindow.polygons.append(merge)

# 选择类别
# self.mainwindow.category_choice_widget.load_cfg()
# self.mainwindow.category_choice_widget.show()
Expand Down
15 changes: 15 additions & 0 deletions ISAT/widgets/mainwindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,11 @@ def reload_cfg(self):
self.cfg['software']['contour_mode'] = contour_mode
self.change_contour_mode(contour_mode)

flatten_selection = software_cfg.get('flatten_selection', False)
self.cfg['software']['flatten_selection'] = flatten_selection
self.menuFlatten_selection.setChecked(flatten_selection)
self.change_flatten_selection()

mask_alpha = software_cfg.get('mask_alpha', 0.5)
self.cfg['software']['mask_alpha'] = mask_alpha
self.mask_aplha.setValue(int(mask_alpha*10))
Expand Down Expand Up @@ -1080,6 +1085,9 @@ def init_connect(self):
self.actionCancel.triggered.connect(self.scene.cancel_draw)
self.actionBackspace.triggered.connect(self.scene.backspace)
self.actionFinish.triggered.connect(self.scene.finish_draw)
self.actionFinishShift.triggered.connect(self.scene.finish_draw)
self.actionFinishAlt.triggered.connect(self.scene.finish_draw)
self.actionFinishShiftAlt.triggered.connect(self.scene.finish_draw)
self.actionEdit.triggered.connect(self.scene.edit_polygon)
self.actionDelete.triggered.connect(self.scene.delete_selected_graph)
self.actionSave.triggered.connect(self.save)
Expand Down Expand Up @@ -1109,7 +1117,14 @@ def init_connect(self):
self.actionChinese.triggered.connect(self.translate_to_chinese)
self.actionEnglish.triggered.connect(self.translate_to_english)

self.menuFlatten_selection.triggered.connect(self.change_flatten_selection)

self.annos_dock_widget.listWidget.doubleClicked.connect(self.scene.edit_polygon)
def change_flatten_selection(self):
checked = self.menuFlatten_selection.isChecked()
self.scene.isFlattenSelection = checked
self.cfg['software']['flatten_selection'] = checked
self.save_software_cfg()

def reset_action(self):
self.actionPrev.setEnabled(False)
Expand Down
4 changes: 3 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ pyyaml
torch>=2.1.1
torchvision
numpy
pycocotools
pycocotools
shapely
keyboard