From 24e1312234ca6e6d131a94c5cdd0f9b92a0f1145 Mon Sep 17 00:00:00 2001 From: iperov Date: Thu, 26 Aug 2021 19:12:34 +0400 Subject: [PATCH] increase preview rendering performance --- .../ui/widgets/QBCFaceAlignViewer.py | 17 +++---- .../ui/widgets/QBCFaceSwapViewer.py | 4 +- .../ui/widgets/QBCFinalFrameViewer.py | 19 ++++---- .../DeepFaceLive/ui/widgets/QBCFrameViewer.py | 11 ++--- xlib/qt/widgets/QXFixedLayeredImages.py | 46 ++++++++++--------- 5 files changed, 47 insertions(+), 50 deletions(-) diff --git a/apps/DeepFaceLive/ui/widgets/QBCFaceAlignViewer.py b/apps/DeepFaceLive/ui/widgets/QBCFaceAlignViewer.py index f3f9c40..6b59298 100644 --- a/apps/DeepFaceLive/ui/widgets/QBCFaceAlignViewer.py +++ b/apps/DeepFaceLive/ui/widgets/QBCFaceAlignViewer.py @@ -19,7 +19,7 @@ class QBCFaceAlignViewer(lib_qt.QXCollapsibleSection): preview_width=256,): self._preview_width = preview_width - self._timer = lib_qt.QXTimer(interval=8, timeout=self._on_timer_8ms, start=True) + self._timer = lib_qt.QXTimer(interval=16, timeout=self._on_timer_16ms, start=True) self._backed_weak_heap = backed_weak_heap self._bc = bc self._bcd_id = None @@ -33,7 +33,7 @@ class QBCFaceAlignViewer(lib_qt.QXCollapsibleSection): (info_label, Qt.AlignmentFlag.AlignCenter), ]) ) - def _on_timer_8ms(self): + def _on_timer_16ms(self): top_qx = self.get_top_QXWindow() if not self.is_opened() or (top_qx is not None and top_qx.is_minimized() ): return @@ -50,12 +50,12 @@ class QBCFaceAlignViewer(lib_qt.QXCollapsibleSection): for face_mark in bcd.get_face_mark_list(): face_align = face_mark.get_face_align() if face_align is not None: - face_align_image_name = face_align.get_image_name() + face_image = bcd.get_image (face_align.get_image_name()) + if face_image is not None: + source_to_aligned_uni_mat = face_align.get_source_to_aligned_uni_mat() - source_to_aligned_uni_mat = face_align.get_source_to_aligned_uni_mat() - - if all_is_not_None(face_align_image_name): - face_image = bcd.get_image(face_align_image_name).copy() + h,w = face_image.shape[:2] + self._layered_images.add_image(face_image) face_ulmrks = face_align.get_face_ulandmarks_by_type(FaceULandmarks.Type.LANDMARKS_468) if face_ulmrks is None: @@ -71,11 +71,8 @@ class QBCFaceAlignViewer(lib_qt.QXCollapsibleSection): aligned_uni_rect = face_mark_rect.transform(source_to_aligned_uni_mat) aligned_uni_rect.draw(lmrks_layer, (0,0,255,255) ) - - self._layered_images.add_image(face_image) self._layered_images.add_image(lmrks_layer) - h,w = face_image.shape[0:2] self._info_label.setText(f'{w}x{h}') diff --git a/apps/DeepFaceLive/ui/widgets/QBCFaceSwapViewer.py b/apps/DeepFaceLive/ui/widgets/QBCFaceSwapViewer.py index 828f661..f7cdec4 100644 --- a/apps/DeepFaceLive/ui/widgets/QBCFaceSwapViewer.py +++ b/apps/DeepFaceLive/ui/widgets/QBCFaceSwapViewer.py @@ -15,7 +15,7 @@ class QBCFaceSwapViewer(lib_qt.QXCollapsibleSection): bc : backend.BackendConnection, preview_width=256,): self._preview_width = preview_width - self._timer = lib_qt.QXTimer(interval=8, timeout=self._on_timer_8ms, start=True) + self._timer = lib_qt.QXTimer(interval=16, timeout=self._on_timer_16ms, start=True) self._backed_weak_heap = backed_weak_heap self._bc = bc @@ -31,7 +31,7 @@ class QBCFaceSwapViewer(lib_qt.QXCollapsibleSection): super().__init__(title=L('@QBCFaceSwapViewer.title'), content_layout=main_l) - def _on_timer_8ms(self): + def _on_timer_16ms(self): top_qx = self.get_top_QXWindow() if not self.is_opened() or (top_qx is not None and top_qx.is_minimized() ): return diff --git a/apps/DeepFaceLive/ui/widgets/QBCFinalFrameViewer.py b/apps/DeepFaceLive/ui/widgets/QBCFinalFrameViewer.py index b77fb16..bf4606b 100644 --- a/apps/DeepFaceLive/ui/widgets/QBCFinalFrameViewer.py +++ b/apps/DeepFaceLive/ui/widgets/QBCFinalFrameViewer.py @@ -1,8 +1,10 @@ +import numpy as np from localization import L from PyQt6.QtCore import * from PyQt6.QtGui import * from PyQt6.QtWidgets import * from resources.fonts import QXFontDB +from xlib import image as lib_image from xlib import qt as lib_qt from ... import backend @@ -12,7 +14,7 @@ class QBCFinalFrameViewer(lib_qt.QXCollapsibleSection): def __init__(self, backed_weak_heap : backend.BackendWeakHeap, bc : backend.BackendConnection, preview_width=256): - self._timer = lib_qt.QXTimer(interval=8, timeout=self._on_timer_8ms, start=True) + self._timer = lib_qt.QXTimer(interval=16, timeout=self._on_timer_16ms, start=True) self._backed_weak_heap = backed_weak_heap self._bc = bc @@ -27,7 +29,7 @@ class QBCFinalFrameViewer(lib_qt.QXCollapsibleSection): ], spacing=0) super().__init__(title=L('@QBCFinalFrameViewer.title'), content_layout=main_l) - def _on_timer_8ms(self): + def _on_timer_16ms(self): top_qx = self.get_top_QXWindow() if not self.is_opened() or (top_qx is not None and top_qx.is_minimized() ): return @@ -42,18 +44,15 @@ class QBCFinalFrameViewer(lib_qt.QXCollapsibleSection): self._layered_images.clear_images() merged_frame_name = bcd.get_merged_frame_name() - merged_frame_image = bcd.get_image(merged_frame_name) - if merged_frame_name is not None and merged_frame_image is not None: + if merged_frame_image is not None: + if merged_frame_image.dtype != np.uint8: + merged_frame_image = lib_image.ImageProcessor(merged_frame_image).to_uint8().get_image('HWC') + self._layered_images.add_image(merged_frame_image) - h,w = merged_frame_image.shape[0:2] - - if merged_frame_name is not None: - self._info_label.setText(f'{merged_frame_name} {w}x{h}') - else: - self._info_label.setText(f'{w}x{h}') + self._info_label.setText(f'{merged_frame_name} {w}x{h}') def clear(self): diff --git a/apps/DeepFaceLive/ui/widgets/QBCFrameViewer.py b/apps/DeepFaceLive/ui/widgets/QBCFrameViewer.py index d8e010d..847f0d5 100644 --- a/apps/DeepFaceLive/ui/widgets/QBCFrameViewer.py +++ b/apps/DeepFaceLive/ui/widgets/QBCFrameViewer.py @@ -1,3 +1,4 @@ +import numpy as np from localization import L from PyQt6.QtCore import * from PyQt6.QtGui import * @@ -12,7 +13,7 @@ class QBCFrameViewer(lib_qt.QXCollapsibleSection): def __init__(self, backed_weak_heap : backend.BackendWeakHeap, bc : backend.BackendConnection, preview_width=256): - self._timer = lib_qt.QXTimer(interval=8, timeout=self._on_timer_8ms, start=True) + self._timer = lib_qt.QXTimer(interval=16, timeout=self._on_timer_16ms, start=True) self._backed_weak_heap = backed_weak_heap self._bc = bc @@ -26,7 +27,7 @@ class QBCFrameViewer(lib_qt.QXCollapsibleSection): ]) super().__init__(title=L('@QBCFrameViewer.title'), content_layout=main_l) - def _on_timer_8ms(self): + def _on_timer_16ms(self): top_qx = self.get_top_QXWindow() if not self.is_opened() or (top_qx is not None and top_qx.is_minimized() ): return @@ -45,10 +46,8 @@ class QBCFrameViewer(lib_qt.QXCollapsibleSection): frame_image = bcd.get_image(frame_name) if frame_image is not None: - self._layered_images.add_image(frame_image) - - h,w = frame_image.shape[0:2] - + self._layered_images.add_image (frame_image) + h,w = frame_image.shape[:2] if frame_name is not None: self._info_label.setText(f'{frame_name} {w}x{h}') else: diff --git a/xlib/qt/widgets/QXFixedLayeredImages.py b/xlib/qt/widgets/QXFixedLayeredImages.py index de07255..c6e8444 100644 --- a/xlib/qt/widgets/QXFixedLayeredImages.py +++ b/xlib/qt/widgets/QXFixedLayeredImages.py @@ -1,47 +1,46 @@ -from typing import List +from typing import List, Union import numpy as np from PyQt6.QtCore import * from PyQt6.QtGui import * from PyQt6.QtWidgets import * -from ...image import ImageProcessor -from ..gui.from_np import QPixmap_from_np +from ..gui.from_np import QImage_from_np from .QXWidget import QXWidget class QXFixedLayeredImages(QXWidget): """ A widget to show multiple stacked images in fixed area + + all images must have the same aspect ratio """ def __init__(self, fixed_width, fixed_height): super().__init__() self._fixed_width = fixed_width self._fixed_height = fixed_height self._qp = QPainter() - self._pixmaps : List[QPixmap] = [] + self._images : List = [] def clear_images(self): - self._pixmaps : List[QPixmap] = [] + self._images : List = [] self.update() def add_image(self, image, name=None): """ - image np.ndarray + image QImage QPixmap - - all images must have the same aspect ratio + np.ndarray of uint8 dtype """ - if isinstance(image, np.ndarray): - ip = ImageProcessor(image) - ip.fit_in(self._fixed_width, self._fixed_height) - image = ip.get_image('HWC') - q_pixmap = QPixmap_from_np(image) - elif isinstance(image, QPixmap): - q_pixmap = image - else: - raise ValueError(f'Unsupported type of image {image.__class__}') + saved_ref = None - self._pixmaps.append(q_pixmap) + if not isinstance(image, QImage) and not isinstance(image, QPixmap): + if isinstance(image, np.ndarray): + saved_ref = image + image = QImage_from_np(image) + else: + raise ValueError(f'Unsupported type of image {image.__class__}') + + self._images.append( (image, saved_ref) ) self.update() def sizeHint(self): @@ -52,7 +51,6 @@ class QXFixedLayeredImages(QXWidget): qp = self._qp qp.begin(self) - #qp.setRenderHint(QPainter.RenderHint.Antialiasing) qp.setRenderHint(QPainter.RenderHint.SmoothPixmapTransform) w = self._fixed_width @@ -62,8 +60,9 @@ class QXFixedLayeredImages(QXWidget): h_half = h /2 a = w/h - for pixmap in self._pixmaps: - size = pixmap.size() + for image, _ in self._images: + + size = image.size() ap = size.width() / size.height() if ap > a: @@ -75,6 +74,9 @@ class QXFixedLayeredImages(QXWidget): else: rect = self.rect() - qp.drawPixmap(rect, pixmap, pixmap.rect()) + if isinstance(image, QImage): + qp.drawImage(rect, image, image.rect()) + elif isinstance(image, QPixmap): + qp.drawPixmap(rect, image, image.rect()) qp.end()