drap 0.0.4.post9__py3-none-any.whl → 0.0.4.post11__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- drap/utils.py +262 -68
- {drap-0.0.4.post9.dist-info → drap-0.0.4.post11.dist-info}/METADATA +1 -1
- {drap-0.0.4.post9.dist-info → drap-0.0.4.post11.dist-info}/RECORD +7 -7
- {drap-0.0.4.post9.dist-info → drap-0.0.4.post11.dist-info}/WHEEL +0 -0
- {drap-0.0.4.post9.dist-info → drap-0.0.4.post11.dist-info}/entry_points.txt +0 -0
- {drap-0.0.4.post9.dist-info → drap-0.0.4.post11.dist-info}/licenses/LICENSE +0 -0
- {drap-0.0.4.post9.dist-info → drap-0.0.4.post11.dist-info}/top_level.txt +0 -0
drap/utils.py
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
from PyQt5.QtWidgets import (QApplication, QProgressDialog, QMainWindow, QLabel, QVBoxLayout, QWidget, QPushButton, QFileDialog,
|
2
2
|
QMessageBox, QLineEdit, QHBoxLayout, QGroupBox, QCheckBox, QSlider, QDialog, QDialogButtonBox,
|
3
|
-
QComboBox)
|
3
|
+
QComboBox, QGridLayout, QSpinBox)
|
4
4
|
from PyQt5.QtGui import QPixmap, QPainter, QPen, QImage, QMouseEvent, QColor
|
5
|
-
from PyQt5.QtCore import Qt, QPoint, QRect, QFileInfo, QTimer, QEvent
|
5
|
+
from PyQt5.QtCore import Qt, QPoint, QRect, QFileInfo, QTimer, QEvent, QSize
|
6
6
|
from fabio.edfimage import EdfImage
|
7
7
|
import tkinter as tk
|
8
8
|
from tkinter import filedialog
|
@@ -105,8 +105,8 @@ class ImageCropper(QMainWindow):
|
|
105
105
|
|
106
106
|
def initUI(self):
|
107
107
|
|
108
|
-
self.test = True
|
109
|
-
|
108
|
+
# self.test = True
|
109
|
+
self.test = False
|
110
110
|
# print("teste")
|
111
111
|
|
112
112
|
|
@@ -140,7 +140,7 @@ class ImageCropper(QMainWindow):
|
|
140
140
|
# Layout de controles do player de vídeo (abaixo do vídeo)
|
141
141
|
self.video_controls_layout = QVBoxLayout()
|
142
142
|
self.image_layout.addLayout(self.video_controls_layout)
|
143
|
-
|
143
|
+
|
144
144
|
# progress bar
|
145
145
|
self.video_slider = QSlider(Qt.Horizontal)
|
146
146
|
self.video_bar_time_layout.addWidget(self.video_slider)
|
@@ -150,8 +150,19 @@ class ImageCropper(QMainWindow):
|
|
150
150
|
self.time_label = QLabel('00:00 / 00:00')
|
151
151
|
self.video_bar_time_layout.addWidget(self.time_label)
|
152
152
|
|
153
|
+
self.info_labels_layout = QHBoxLayout()
|
153
154
|
self.mouse_label = QLabel('Mouse: (0,0)')
|
154
|
-
self.
|
155
|
+
self.image_size_label = QLabel("Image size: 0 x 0")
|
156
|
+
|
157
|
+
self.info_labels_layout.addWidget(self.mouse_label)
|
158
|
+
self.info_labels_layout.addWidget(self.image_size_label)
|
159
|
+
self.info_labels_layout.addStretch()
|
160
|
+
|
161
|
+
|
162
|
+
self.video_bar_time_layout.addLayout(self.info_labels_layout)
|
163
|
+
|
164
|
+
|
165
|
+
# self.video_bar_time_layout.addWidget(self.image_size_label)
|
155
166
|
|
156
167
|
# Timer para reprodução de vídeo
|
157
168
|
self.video_timer = QTimer()
|
@@ -205,6 +216,41 @@ class ImageCropper(QMainWindow):
|
|
205
216
|
self.speed_slider.valueChanged.connect(self.update_speed)
|
206
217
|
|
207
218
|
|
219
|
+
# === Painel de coordenadas do retângulo ===
|
220
|
+
self.rect_group = QGroupBox("Rectangle Position and Size")
|
221
|
+
self.rect_layout = QGridLayout()
|
222
|
+
self.rect_group.setLayout(self.rect_layout)
|
223
|
+
|
224
|
+
# Cria os 4 campos (x, y, largura, altura)
|
225
|
+
self.rect_x_spin = QSpinBox()
|
226
|
+
self.rect_y_spin = QSpinBox()
|
227
|
+
self.rect_w_spin = QSpinBox()
|
228
|
+
self.rect_h_spin = QSpinBox()
|
229
|
+
|
230
|
+
# Rótulos
|
231
|
+
self.rect_layout.addWidget(QLabel("X:"), 0, 0)
|
232
|
+
self.rect_layout.addWidget(self.rect_x_spin, 0, 1)
|
233
|
+
self.rect_layout.addWidget(QLabel("Y:"), 0, 2)
|
234
|
+
self.rect_layout.addWidget(self.rect_y_spin, 0, 3)
|
235
|
+
self.rect_layout.addWidget(QLabel("Width:"), 1, 0)
|
236
|
+
self.rect_layout.addWidget(self.rect_w_spin, 1, 1)
|
237
|
+
self.rect_layout.addWidget(QLabel("Height:"), 1, 2)
|
238
|
+
self.rect_layout.addWidget(self.rect_h_spin, 1, 3)
|
239
|
+
|
240
|
+
# Adiciona ao layout principal lateral
|
241
|
+
self.video_controls_layout.addWidget(self.rect_group)
|
242
|
+
|
243
|
+
# Limites padrão (atualizados quando o vídeo é carregado)
|
244
|
+
for spin in [self.rect_x_spin, self.rect_y_spin, self.rect_w_spin, self.rect_h_spin]:
|
245
|
+
spin.setRange(0, 9999)
|
246
|
+
spin.setSingleStep(1)
|
247
|
+
|
248
|
+
# Conectar mudanças dos campos ao redesenho do retângulo
|
249
|
+
self.rect_x_spin.valueChanged.connect(self.update_rect_from_spinboxes)
|
250
|
+
self.rect_y_spin.valueChanged.connect(self.update_rect_from_spinboxes)
|
251
|
+
self.rect_w_spin.valueChanged.connect(self.update_rect_from_spinboxes)
|
252
|
+
self.rect_h_spin.valueChanged.connect(self.update_rect_from_spinboxes)
|
253
|
+
|
208
254
|
|
209
255
|
|
210
256
|
# Layout to controls
|
@@ -323,8 +369,8 @@ class ImageCropper(QMainWindow):
|
|
323
369
|
if self.test:
|
324
370
|
self.load_image()
|
325
371
|
self.int_input1.setText("45.")
|
326
|
-
self.int_input2.setText("
|
327
|
-
self.int_input3.setText("
|
372
|
+
self.int_input2.setText("1")
|
373
|
+
self.int_input3.setText("25")
|
328
374
|
self.int_input4.setText("1.0")
|
329
375
|
|
330
376
|
self.show()
|
@@ -337,7 +383,8 @@ class ImageCropper(QMainWindow):
|
|
337
383
|
|
338
384
|
|
339
385
|
if self.test:
|
340
|
-
self.file_path = "/home/standard02/Documents/programming/python/bolhas/
|
386
|
+
self.file_path = "/home/standard02/Documents/programming/python/bolhas/PyPI/drap/teste.mp4"
|
387
|
+
# "/home/standard02/Documents/programming/python/bolhas/PyPI/drap/teste_completo.mp4" teste_bolha.mp4
|
341
388
|
# self.file_path, _ = QFileDialog.getOpenFileName(self, 'Open Video', '', 'Videos (*.avi *.mp4 *.mov *.mkv *.wmv *.flv *.mpg *.mpeg *.3gp *.ogv .webm)')
|
342
389
|
else:
|
343
390
|
self.file_path, _ = QFileDialog.getOpenFileName(self, 'Open Video', '', 'Videos (*.avi *.mp4 *.mov *.mkv *.wmv *.flv *.mpg *.mpeg *.3gp *.ogv .webm)')
|
@@ -379,9 +426,30 @@ class ImageCropper(QMainWindow):
|
|
379
426
|
self.image = qimg.copy()
|
380
427
|
self.pixmap = QPixmap.fromImage(self.image)
|
381
428
|
self.image_label.setPixmap(self.pixmap) #show image
|
429
|
+
self.image_label.adjustSize()
|
430
|
+
self.original_image = self.pixmap.toImage()
|
382
431
|
# self.image_label.setScaledContents(True)
|
432
|
+
self.image_label.setScaledContents(False)
|
433
|
+
self.image_label.setAlignment(Qt.AlignCenter)
|
434
|
+
|
435
|
+
|
436
|
+
self.image_width = self.pixmap.width()
|
437
|
+
self.image_height = self.pixmap.height()
|
438
|
+
self.update_rect_limits()
|
439
|
+
|
383
440
|
self.current_rect = QRect()
|
384
|
-
self.update_image()
|
441
|
+
self.update_image()
|
442
|
+
self.img_size = [frame.shape[1], frame.shape[0]]
|
443
|
+
|
444
|
+
self.image_size_label.setText(f"Image size: {self.img_size[1]} × {self.img_size[0]}")
|
445
|
+
|
446
|
+
# Limitar X e Y dentro dos limites da imagem
|
447
|
+
self.rect_x_spin.setRange(0, self.img_size[0] - 1 )
|
448
|
+
self.rect_y_spin.setRange(0, self.img_size[1] - 1 )
|
449
|
+
|
450
|
+
# Limitar largura e altura para não ultrapassar o tamanho da imagem
|
451
|
+
self.rect_w_spin.setRange(0, self.img_size[0] - self.rect_x_spin.value())
|
452
|
+
self.rect_h_spin.setRange(0, self.img_size[1] - self.rect_y_spin.value())
|
385
453
|
|
386
454
|
# Reseta variáveis de estado
|
387
455
|
self.fps = int(self.video.get(cv2.CAP_PROP_FPS))
|
@@ -485,8 +553,12 @@ class ImageCropper(QMainWindow):
|
|
485
553
|
self.image = q_image.copy()
|
486
554
|
self.pixmap = QPixmap.fromImage(self.image)
|
487
555
|
self.image_label.setPixmap(self.pixmap)
|
488
|
-
|
489
|
-
self.
|
556
|
+
self.image_label.adjustSize()
|
557
|
+
self.image_label.setPixmap(self.pixmap)
|
558
|
+
self.image_width = w
|
559
|
+
self.image_height = h
|
560
|
+
self.update_rect_limits()
|
561
|
+
# self.update_image()
|
490
562
|
|
491
563
|
|
492
564
|
|
@@ -505,7 +577,7 @@ class ImageCropper(QMainWindow):
|
|
505
577
|
|
506
578
|
current_time = self.current_frame / self.fps if self.fps else 0
|
507
579
|
total_time = self.total_frames / self.fps if self.fps else 0
|
508
|
-
time_str = f"{self.format_time(current_time)}
|
580
|
+
time_str = f"{self.format_time(current_time)} min / {self.format_time(total_time)} min ({current_time:.2f} s - frame: {self.current_frame})"
|
509
581
|
self.time_label.setText(time_str)
|
510
582
|
|
511
583
|
def format_time(self, seconds):
|
@@ -569,7 +641,7 @@ class ImageCropper(QMainWindow):
|
|
569
641
|
layout.addWidget(end_input)
|
570
642
|
|
571
643
|
# keep decider when the frame will save
|
572
|
-
keep_decider_label = QLabel("
|
644
|
+
keep_decider_label = QLabel("Keep frames each second:")
|
573
645
|
keep_decider_input = QLineEdit(str(self.fps))
|
574
646
|
layout.addWidget(keep_decider_label)
|
575
647
|
layout.addWidget(keep_decider_input)
|
@@ -621,26 +693,18 @@ class ImageCropper(QMainWindow):
|
|
621
693
|
|
622
694
|
w_in = int(video_in.get(cv2.CAP_PROP_FRAME_WIDTH))
|
623
695
|
h_in = int(video_in.get(cv2.CAP_PROP_FRAME_HEIGHT))
|
624
|
-
display_w = self.image_label.width()
|
625
|
-
display_h = self.image_label.height()
|
626
|
-
scale_x = w_in / display_w
|
627
|
-
scale_y = h_in / display_h
|
628
696
|
|
629
697
|
|
630
698
|
if crop_rect is not None:
|
631
699
|
x, y, w_out, h_out = crop_rect
|
632
|
-
x =
|
633
|
-
y =
|
634
|
-
w_out =
|
635
|
-
h_out =
|
636
|
-
|
637
|
-
# x = max(0, min(x, w_in - 1))
|
638
|
-
# y = max(0, min(y, h_in - 1))
|
639
|
-
# w_out = min(w_out, w_in - x)
|
640
|
-
# h_out = min(h_out, h_in - y)
|
700
|
+
x = max(0, min(x, w_in - 1))
|
701
|
+
y = max(0, min(y, h_in - 1))
|
702
|
+
w_out = min(w_out, w_in - x)
|
703
|
+
h_out = min(h_out, h_in - y)
|
704
|
+
|
641
705
|
else:
|
642
|
-
|
643
|
-
h_out = h_in
|
706
|
+
x, y = 0, 0
|
707
|
+
w_out, h_out = w_in, h_in
|
644
708
|
|
645
709
|
size = (abs(w_out), abs(h_out))
|
646
710
|
|
@@ -774,28 +838,21 @@ class ImageCropper(QMainWindow):
|
|
774
838
|
return None
|
775
839
|
|
776
840
|
label_size = self.image_label.size()
|
777
|
-
|
778
|
-
pm_size = pm.size()
|
841
|
+
pixmap_size = self.pixmap.size()
|
779
842
|
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
x_off = (label_size.width() - scaled_pm.width()) // 2
|
784
|
-
y_off = (label_size.height() - scaled_pm.height()) // 2
|
843
|
+
# Calcula o offset (bordas pretas) se a imagem estiver centralizada
|
844
|
+
x_offset = max((label_size.width() - pixmap_size.width()) // 2, 0)
|
845
|
+
y_offset = max((label_size.height() - pixmap_size.height()) // 2, 0)
|
785
846
|
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
if sx < 0 or sy < 0 or sx >= scaled_pm.width() or sy >= scaled_pm.height():
|
790
|
-
return None # fora da imagem
|
847
|
+
# Remove o deslocamento
|
848
|
+
x = pos.x() - x_offset
|
849
|
+
y = pos.y() - y_offset
|
791
850
|
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
return QPoint(ix, iy)
|
851
|
+
# Garante que está dentro da imagem
|
852
|
+
if 0 <= x < pixmap_size.width() and 0 <= y < pixmap_size.height():
|
853
|
+
return QPoint(x, y)
|
854
|
+
else:
|
855
|
+
return None
|
799
856
|
|
800
857
|
|
801
858
|
|
@@ -995,36 +1052,48 @@ class ImageCropper(QMainWindow):
|
|
995
1052
|
|
996
1053
|
def eventFilter(self, obj, event):
|
997
1054
|
|
998
|
-
|
999
|
-
|
1000
|
-
|
1055
|
+
if obj == self.image_label and (self.original_image is not None):
|
1056
|
+
|
1057
|
+
# Atualiza posição do mouse (mesmo sem clicar)
|
1058
|
+
if event.type() == QEvent.MouseMove:
|
1059
|
+
pos = event.pos()
|
1060
|
+
mapped = self.label_pos_to_image_pos(pos)
|
1061
|
+
if mapped:
|
1062
|
+
self.mouse_label.setText(f"Mouse: ({mapped.x()}, {mapped.y()})")
|
1063
|
+
|
1064
|
+
# Início do desenho do retângulo
|
1001
1065
|
if event.type() == QEvent.MouseButtonPress and event.button() == Qt.LeftButton:
|
1002
1066
|
mapped = self.label_pos_to_image_pos(event.pos())
|
1003
1067
|
if mapped is not None:
|
1004
1068
|
self.drawing = True
|
1005
1069
|
self.rect_start = mapped
|
1006
|
-
self.current_rect = QRect(self.rect_start,
|
1007
|
-
self.update_image()
|
1070
|
+
self.current_rect = QRect(self.rect_start, QSize())
|
1071
|
+
self.update_image() # desenha imediatamente, sem atualizar limites
|
1072
|
+
self.update_spinboxes_from_rect()
|
1008
1073
|
|
1009
|
-
|
1074
|
+
# Movimento do mouse durante o desenho
|
1075
|
+
elif event.type() == QEvent.MouseMove and getattr(self, "drawing", False):
|
1010
1076
|
mapped = self.label_pos_to_image_pos(event.pos())
|
1011
1077
|
if mapped is not None:
|
1012
1078
|
self.current_rect = QRect(self.rect_start, mapped).normalized()
|
1013
|
-
self.update_image()
|
1079
|
+
self.update_image() # redesenha em tempo real (não mexe nos spinboxes ainda)
|
1014
1080
|
|
1081
|
+
# Soltar o botão: finalize o desenho
|
1015
1082
|
elif event.type() == QEvent.MouseButtonRelease and event.button() == Qt.LeftButton:
|
1016
|
-
if self
|
1017
|
-
self.drawing = False
|
1083
|
+
if getattr(self, "drawing", False):
|
1084
|
+
# self.drawing = False
|
1018
1085
|
mapped = self.label_pos_to_image_pos(event.pos())
|
1019
1086
|
if mapped is not None:
|
1020
1087
|
self.current_rect = QRect(self.rect_start, mapped).normalized()
|
1021
|
-
self.update_image()
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1088
|
+
self.update_image() # mantém o desenho visível
|
1089
|
+
self.update_spinboxes_from_rect() # atualiza campos
|
1090
|
+
self.update_rect_limits() # aplica os limites só no final
|
1091
|
+
self.drawing = False
|
1092
|
+
|
1025
1093
|
return super().eventFilter(obj, event)
|
1026
1094
|
|
1027
1095
|
|
1096
|
+
|
1028
1097
|
def crop_image(self):
|
1029
1098
|
|
1030
1099
|
if not hasattr(self, "original_image") or self.original_image is None:
|
@@ -1075,7 +1144,7 @@ class ImageCropper(QMainWindow):
|
|
1075
1144
|
else:
|
1076
1145
|
print_pdf = False
|
1077
1146
|
|
1078
|
-
if hasattr(self, 'ret'):
|
1147
|
+
if hasattr(self, 'ret') and self.ret is not None:
|
1079
1148
|
pass;
|
1080
1149
|
else:
|
1081
1150
|
QMessageBox.warning(self, '', 'No rectangle drawn for cropping. Please draw rectangle first and cut the image.')
|
@@ -1091,14 +1160,133 @@ class ImageCropper(QMainWindow):
|
|
1091
1160
|
result_image = set_file_1.read_video();
|
1092
1161
|
if result_image:
|
1093
1162
|
self.result_image = QPixmap(result_image)
|
1094
|
-
self.original_image = self.result_image.toImage()
|
1095
1163
|
self.image = self.result_image.toImage()
|
1096
|
-
self.result_label.setPixmap(QPixmap.fromImage(self.
|
1097
|
-
self.result_label.setScaledContents(True)
|
1164
|
+
self.result_label.setPixmap(QPixmap.fromImage(self.image))
|
1165
|
+
# self.result_label.setScaledContents(True)
|
1098
1166
|
else:
|
1099
1167
|
QMessageBox.warning(self, 'Warning', 'Please Fill the forms.')
|
1100
1168
|
return;
|
1101
1169
|
|
1170
|
+
def update_rect_from_spinboxes(self):
|
1171
|
+
"""Atualiza o retângulo quando o usuário muda os valores manualmente."""
|
1172
|
+
if not hasattr(self, "current_rect"):
|
1173
|
+
self.current_rect = QRect()
|
1174
|
+
|
1175
|
+
# Se o usuário estiver desenhando, ignore alterações manuais temporariamente
|
1176
|
+
if getattr(self, "drawing", False):
|
1177
|
+
return
|
1178
|
+
|
1179
|
+
if not hasattr(self, "pixmap") or self.pixmap.isNull():
|
1180
|
+
return
|
1181
|
+
|
1182
|
+
img_width = self.pixmap.width()
|
1183
|
+
img_height = self.pixmap.height()
|
1184
|
+
|
1185
|
+
x = self.rect_x_spin.value()
|
1186
|
+
y = self.rect_y_spin.value()
|
1187
|
+
w = self.rect_w_spin.value()
|
1188
|
+
h = self.rect_h_spin.value()
|
1189
|
+
|
1190
|
+
# Ajusta se ultrapassar a borda direita ou inferior
|
1191
|
+
if x + w > img_width:
|
1192
|
+
w = img_width - x
|
1193
|
+
self.rect_w_spin.blockSignals(True)
|
1194
|
+
self.rect_w_spin.setValue(w)
|
1195
|
+
self.rect_w_spin.blockSignals(False)
|
1196
|
+
|
1197
|
+
if y + h > img_height:
|
1198
|
+
h = img_height - y
|
1199
|
+
self.rect_h_spin.blockSignals(True)
|
1200
|
+
self.rect_h_spin.setValue(h)
|
1201
|
+
self.rect_h_spin.blockSignals(False)
|
1202
|
+
|
1203
|
+
# 🔹 Garante que x, y não fiquem fora da imagem
|
1204
|
+
if x < 0:
|
1205
|
+
x = 0
|
1206
|
+
self.rect_x_spin.blockSignals(True)
|
1207
|
+
self.rect_x_spin.setValue(0)
|
1208
|
+
self.rect_x_spin.blockSignals(False)
|
1209
|
+
|
1210
|
+
if y < 0:
|
1211
|
+
y = 0
|
1212
|
+
self.rect_y_spin.blockSignals(True)
|
1213
|
+
self.rect_y_spin.setValue(0)
|
1214
|
+
self.rect_y_spin.blockSignals(False)
|
1215
|
+
|
1216
|
+
# 🔹 Atualiza o retângulo e redesenha
|
1217
|
+
self.current_rect = QRect(x, y, w, h)
|
1218
|
+
self.update_image()
|
1219
|
+
|
1220
|
+
|
1221
|
+
|
1222
|
+
def update_spinboxes_from_rect(self):
|
1223
|
+
"""Atualiza os campos (x, y, largura, altura) com base no retângulo atual desenhado."""
|
1224
|
+
if not hasattr(self, "current_rect") or self.current_rect.isNull():
|
1225
|
+
return
|
1226
|
+
|
1227
|
+
rect = self.current_rect
|
1228
|
+
|
1229
|
+
# Evita loops infinitos de sinal: desliga os sinais temporariamente
|
1230
|
+
self.rect_x_spin.blockSignals(True)
|
1231
|
+
self.rect_y_spin.blockSignals(True)
|
1232
|
+
self.rect_w_spin.blockSignals(True)
|
1233
|
+
self.rect_h_spin.blockSignals(True)
|
1234
|
+
|
1235
|
+
# Atualiza os valores dos campos com o retângulo atual
|
1236
|
+
self.rect_x_spin.setValue(rect.x())
|
1237
|
+
self.rect_y_spin.setValue(rect.y())
|
1238
|
+
self.rect_w_spin.setValue(rect.width())
|
1239
|
+
self.rect_h_spin.setValue(rect.height())
|
1240
|
+
|
1241
|
+
# Reativa os sinais
|
1242
|
+
self.rect_x_spin.blockSignals(False)
|
1243
|
+
self.rect_y_spin.blockSignals(False)
|
1244
|
+
self.rect_w_spin.blockSignals(False)
|
1245
|
+
self.rect_h_spin.blockSignals(False)
|
1246
|
+
|
1247
|
+
def update_rect_limits(self):
|
1248
|
+
|
1249
|
+
|
1250
|
+
if not hasattr(self, "pixmap") or self.pixmap.isNull():
|
1251
|
+
return
|
1252
|
+
|
1253
|
+
# Se o usuário está desenhando, não interfere
|
1254
|
+
if getattr(self, "drawing", False):
|
1255
|
+
return
|
1256
|
+
|
1257
|
+
img_width = getattr(self, "image_width", self.pixmap.width())
|
1258
|
+
img_height = getattr(self, "image_height", self.pixmap.height())
|
1259
|
+
|
1260
|
+
x = self.rect_x_spin.value()
|
1261
|
+
y = self.rect_y_spin.value()
|
1262
|
+
w = self.rect_w_spin.value()
|
1263
|
+
h = self.rect_h_spin.value()
|
1264
|
+
|
1265
|
+
# Define novos limites
|
1266
|
+
self.rect_x_spin.setRange(0, img_width - 1)
|
1267
|
+
self.rect_y_spin.setRange(0, img_height - 1)
|
1268
|
+
self.rect_w_spin.setRange(1, img_width - x)
|
1269
|
+
self.rect_h_spin.setRange(1, img_height - y)
|
1270
|
+
|
1271
|
+
# Se os valores atuais de largura/altura ultrapassarem os limites, reduza automaticamente
|
1272
|
+
if x + w > img_width:
|
1273
|
+
self.rect_w_spin.setValue(img_width - x)
|
1274
|
+
self.rect_w_spin.blockSignals(True)
|
1275
|
+
self.rect_w_spin.setValue(img_width - x)
|
1276
|
+
self.rect_w_spin.blockSignals(False)
|
1277
|
+
|
1278
|
+
if y + h > img_height:
|
1279
|
+
self.rect_h_spin.setValue(img_height - y)
|
1280
|
+
self.rect_h_spin.blockSignals(True)
|
1281
|
+
self.rect_h_spin.setValue(img_height - y)
|
1282
|
+
self.rect_h_spin.blockSignals(False)
|
1283
|
+
|
1284
|
+
# Só atualiza o retângulo se o usuário não estiver desenhando com o mouse
|
1285
|
+
if not getattr(self, "drawing", False):
|
1286
|
+
self.current_rect = QRect(x, y, self.rect_w_spin.value(), self.rect_h_spin.value())
|
1287
|
+
self.update_image()
|
1288
|
+
|
1289
|
+
|
1102
1290
|
|
1103
1291
|
def update_image(self, frame=None):
|
1104
1292
|
|
@@ -2145,6 +2333,7 @@ class conc_scat_video:
|
|
2145
2333
|
data_time_size[data_i][0] = time; # time
|
2146
2334
|
data_time_size[data_i][1] = (width / 2.) / (self.px_mm ); # width -> semi axes
|
2147
2335
|
data_time_size[data_i][2] = (height/ 2.) / (self.px_mm); # height -> semi axes
|
2336
|
+
|
2148
2337
|
if data_i == 0:
|
2149
2338
|
self.Vo = calcule_vol_spheroide(data_time_size[data_i][1], data_time_size[data_i][2] ) / 1000. # use in mL
|
2150
2339
|
temp = datetime.fromtimestamp(self.video_m) + timedelta(seconds=time);
|
@@ -2171,7 +2360,7 @@ class conc_scat_video:
|
|
2171
2360
|
# temp_m[flag_temp,1] = temp_m[flag_temp,1] - 1
|
2172
2361
|
# if temp_m[flag_temp,1] < 1: flag_temp = flag_temp + 1;
|
2173
2362
|
|
2174
|
-
|
2363
|
+
|
2175
2364
|
|
2176
2365
|
data_i = data_i +1;
|
2177
2366
|
# cv2.imshow("image fim", imagem)
|
@@ -2184,7 +2373,7 @@ class conc_scat_video:
|
|
2184
2373
|
progress.update(frame_count, elapsed_time)
|
2185
2374
|
if progress.was_canceled():
|
2186
2375
|
progress.finish()
|
2187
|
-
print("Process canceled by user.")
|
2376
|
+
# print("Process canceled by user.")
|
2188
2377
|
return None
|
2189
2378
|
|
2190
2379
|
has_frame, frame = video.read()
|
@@ -2194,10 +2383,12 @@ class conc_scat_video:
|
|
2194
2383
|
|
2195
2384
|
|
2196
2385
|
new_data_time_size = delete_value_extrem(data_time_size);
|
2386
|
+
|
2197
2387
|
self.coef_pol_w = numpy.polyfit(new_data_time_size[:, 0],new_data_time_size[:, 1],12);
|
2198
2388
|
self.coef_pol_h = numpy.polyfit(new_data_time_size[:, 0],new_data_time_size[:, 2],12);
|
2199
2389
|
self.coef_pol_area = numpy.polyfit(new_data_time_size[:, 0],new_data_time_size[:, 6],12);
|
2200
2390
|
self.coef_pol_conc = numpy.polyfit(new_data_time_size[:, 0],new_data_time_size[:, 7],12);
|
2391
|
+
|
2201
2392
|
|
2202
2393
|
|
2203
2394
|
|
@@ -2205,6 +2396,7 @@ class conc_scat_video:
|
|
2205
2396
|
file_out = os.path.join(path_dir_imgs,self.name_file+'_Video_time_size.csv');
|
2206
2397
|
file_out = os.path.normpath(file_out);
|
2207
2398
|
save_data_video(new_data_time_size,self.coef_pol_w, self.coef_pol_h, self.coef_pol_area, self.coef_pol_conc, file_out);
|
2399
|
+
|
2208
2400
|
|
2209
2401
|
|
2210
2402
|
file_out = os.path.join(path_dir_imgs,self.name_file+'_sizes.png');
|
@@ -2311,9 +2503,11 @@ def save_data_video(data_in, coef_w, coef_h, coef_area, coef_conc, output_file):
|
|
2311
2503
|
file_op.write(f"Coeficient concentration: {', '.join([f'{i_coef:.7e}' for i_coef in coef_conc])}\n")
|
2312
2504
|
file_op.write("Frame,dropDX(mm),dropDY(mm),surface(mm^2),Volume(\u03bcL),RelativeConcentration(%),date,time(s),time(min)\n")
|
2313
2505
|
|
2506
|
+
|
2314
2507
|
for i_data in range(0, len(data_in)):
|
2315
2508
|
|
2316
|
-
|
2509
|
+
|
2510
|
+
str_ = f"{int(data_in[i_data,4]):>5d}, {data_in[i_data,1]:.3e}, {data_in[i_data,2]:.3e}, {data_in[i_data,6]:.3e}, {data_in[i_data,8]:.3e}, {data_in[i_data,7]:.3e}, {datetime.fromtimestamp(data_in[i_data,3]).strftime('%Y-%m-%d %H:%M:%S')}, {data_in[i_data,0]:.2f}, {data_in[i_data,4]:.2f} \n";
|
2317
2511
|
|
2318
2512
|
file_op.write(str_);
|
2319
2513
|
file_op.close()
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: drap
|
3
|
-
Version: 0.0.4.
|
3
|
+
Version: 0.0.4.post11
|
4
4
|
Summary: Tool for analyzing droplet size and concentration using video and EDF images
|
5
5
|
Author-email: "Gabriel Braga Marques Teobaldo, Oleg Prymak, Natalie Wolff, Matthias Epple, Marco Aurélio Brizzotti Andrade, Cássio Alves and Cristiano Luis Pinto de Oliveira" <crislpo@ufpr.br>
|
6
6
|
License: MIT
|
@@ -4,13 +4,13 @@ drap/gui.py,sha256=LzBBQwFiF6IcOZfBkWB6wnKsBKD-v-6Un8VoJMG7eKU,1553
|
|
4
4
|
drap/main.py,sha256=FHiki3tcip7BOvsEFxVacdienu1D3QHneuXEidBfBXs,1200
|
5
5
|
drap/qt_adjust.py,sha256=Ru99Qz_5bqxwDNGxREQnF17BZ0Nda0eeuQvH2-w98S8,1317
|
6
6
|
drap/terminal_interface.py,sha256=vCnobMdtxKvCUaFsu0fWmChd65a-Osn41LdMtSdMdO4,2201
|
7
|
-
drap/utils.py,sha256=
|
7
|
+
drap/utils.py,sha256=Vq5lI1SAEHH-ZykytOFVzoG2QEJuFXUExVEEigKsH8A,104017
|
8
8
|
drap/resources/DrapuserGuide_eng.pdf,sha256=EF9GwitgqOB9MPAWta6fXgPTaKU6O8_ERCcb6mbrj4A,553887
|
9
9
|
drap/resources/DrapuserGuide_pt.pdf,sha256=KjbIWg5df5eAWFtx4eGFUcIb6ktTlHG8bztMk6l0_d4,547977
|
10
10
|
drap/resources/name_videos.dat,sha256=-BC_xVXnRDN-zIcQk95_DUi0WLbmARlap2ML9N8LszI,481
|
11
|
-
drap-0.0.4.
|
12
|
-
drap-0.0.4.
|
13
|
-
drap-0.0.4.
|
14
|
-
drap-0.0.4.
|
15
|
-
drap-0.0.4.
|
16
|
-
drap-0.0.4.
|
11
|
+
drap-0.0.4.post11.dist-info/licenses/LICENSE,sha256=iHcEhVN-5ifqXsDa1Ny38sIBS7SJ9-eYJQRtHiJ3QU0,1098
|
12
|
+
drap-0.0.4.post11.dist-info/METADATA,sha256=TKQpRaOxdqKIgrz-AYd7H5Ek8Qo18Xwq9I1k8bafH8E,1492
|
13
|
+
drap-0.0.4.post11.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
14
|
+
drap-0.0.4.post11.dist-info/entry_points.txt,sha256=8AnGrT_RVCkh26SYRqjRTbstT4BMuOO68qRFqPfPr8M,69
|
15
|
+
drap-0.0.4.post11.dist-info/top_level.txt,sha256=jYMnBoijRdvPMYoMlILxlRNbSdKUX3_uwMa7DLRE4zE,5
|
16
|
+
drap-0.0.4.post11.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|