increase preview rendering performance

This commit is contained in:
iperov 2021-08-26 19:12:34 +04:00
commit 24e1312234
5 changed files with 47 additions and 50 deletions

View file

@ -19,7 +19,7 @@ class QBCFaceAlignViewer(lib_qt.QXCollapsibleSection):
preview_width=256,): preview_width=256,):
self._preview_width = preview_width 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._backed_weak_heap = backed_weak_heap
self._bc = bc self._bc = bc
self._bcd_id = None self._bcd_id = None
@ -33,7 +33,7 @@ class QBCFaceAlignViewer(lib_qt.QXCollapsibleSection):
(info_label, Qt.AlignmentFlag.AlignCenter), (info_label, Qt.AlignmentFlag.AlignCenter),
]) ) ]) )
def _on_timer_8ms(self): def _on_timer_16ms(self):
top_qx = self.get_top_QXWindow() top_qx = self.get_top_QXWindow()
if not self.is_opened() or (top_qx is not None and top_qx.is_minimized() ): if not self.is_opened() or (top_qx is not None and top_qx.is_minimized() ):
return return
@ -50,12 +50,12 @@ class QBCFaceAlignViewer(lib_qt.QXCollapsibleSection):
for face_mark in bcd.get_face_mark_list(): for face_mark in bcd.get_face_mark_list():
face_align = face_mark.get_face_align() face_align = face_mark.get_face_align()
if face_align is not None: 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() h,w = face_image.shape[:2]
self._layered_images.add_image(face_image)
if all_is_not_None(face_align_image_name):
face_image = bcd.get_image(face_align_image_name).copy()
face_ulmrks = face_align.get_face_ulandmarks_by_type(FaceULandmarks.Type.LANDMARKS_468) face_ulmrks = face_align.get_face_ulandmarks_by_type(FaceULandmarks.Type.LANDMARKS_468)
if face_ulmrks is None: 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 = face_mark_rect.transform(source_to_aligned_uni_mat)
aligned_uni_rect.draw(lmrks_layer, (0,0,255,255) ) aligned_uni_rect.draw(lmrks_layer, (0,0,255,255) )
self._layered_images.add_image(face_image)
self._layered_images.add_image(lmrks_layer) self._layered_images.add_image(lmrks_layer)
h,w = face_image.shape[0:2]
self._info_label.setText(f'{w}x{h}') self._info_label.setText(f'{w}x{h}')

View file

@ -15,7 +15,7 @@ class QBCFaceSwapViewer(lib_qt.QXCollapsibleSection):
bc : backend.BackendConnection, bc : backend.BackendConnection,
preview_width=256,): preview_width=256,):
self._preview_width = preview_width 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._backed_weak_heap = backed_weak_heap
self._bc = bc self._bc = bc
@ -31,7 +31,7 @@ class QBCFaceSwapViewer(lib_qt.QXCollapsibleSection):
super().__init__(title=L('@QBCFaceSwapViewer.title'), content_layout=main_l) 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() top_qx = self.get_top_QXWindow()
if not self.is_opened() or (top_qx is not None and top_qx.is_minimized() ): if not self.is_opened() or (top_qx is not None and top_qx.is_minimized() ):
return return

View file

@ -1,8 +1,10 @@
import numpy as np
from localization import L from localization import L
from PyQt6.QtCore import * from PyQt6.QtCore import *
from PyQt6.QtGui import * from PyQt6.QtGui import *
from PyQt6.QtWidgets import * from PyQt6.QtWidgets import *
from resources.fonts import QXFontDB from resources.fonts import QXFontDB
from xlib import image as lib_image
from xlib import qt as lib_qt from xlib import qt as lib_qt
from ... import backend from ... import backend
@ -12,7 +14,7 @@ class QBCFinalFrameViewer(lib_qt.QXCollapsibleSection):
def __init__(self, backed_weak_heap : backend.BackendWeakHeap, def __init__(self, backed_weak_heap : backend.BackendWeakHeap,
bc : backend.BackendConnection, bc : backend.BackendConnection,
preview_width=256): 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._backed_weak_heap = backed_weak_heap
self._bc = bc self._bc = bc
@ -27,7 +29,7 @@ class QBCFinalFrameViewer(lib_qt.QXCollapsibleSection):
], spacing=0) ], spacing=0)
super().__init__(title=L('@QBCFinalFrameViewer.title'), content_layout=main_l) 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() top_qx = self.get_top_QXWindow()
if not self.is_opened() or (top_qx is not None and top_qx.is_minimized() ): if not self.is_opened() or (top_qx is not None and top_qx.is_minimized() ):
return return
@ -42,18 +44,15 @@ class QBCFinalFrameViewer(lib_qt.QXCollapsibleSection):
self._layered_images.clear_images() self._layered_images.clear_images()
merged_frame_name = bcd.get_merged_frame_name() merged_frame_name = bcd.get_merged_frame_name()
merged_frame_image = bcd.get_image(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) self._layered_images.add_image(merged_frame_image)
h,w = merged_frame_image.shape[0:2] h,w = merged_frame_image.shape[0:2]
self._info_label.setText(f'{merged_frame_name} {w}x{h}')
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}')
def clear(self): def clear(self):

View file

@ -1,3 +1,4 @@
import numpy as np
from localization import L from localization import L
from PyQt6.QtCore import * from PyQt6.QtCore import *
from PyQt6.QtGui import * from PyQt6.QtGui import *
@ -12,7 +13,7 @@ class QBCFrameViewer(lib_qt.QXCollapsibleSection):
def __init__(self, backed_weak_heap : backend.BackendWeakHeap, def __init__(self, backed_weak_heap : backend.BackendWeakHeap,
bc : backend.BackendConnection, bc : backend.BackendConnection,
preview_width=256): 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._backed_weak_heap = backed_weak_heap
self._bc = bc self._bc = bc
@ -26,7 +27,7 @@ class QBCFrameViewer(lib_qt.QXCollapsibleSection):
]) ])
super().__init__(title=L('@QBCFrameViewer.title'), content_layout=main_l) 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() top_qx = self.get_top_QXWindow()
if not self.is_opened() or (top_qx is not None and top_qx.is_minimized() ): if not self.is_opened() or (top_qx is not None and top_qx.is_minimized() ):
return return
@ -45,10 +46,8 @@ class QBCFrameViewer(lib_qt.QXCollapsibleSection):
frame_image = bcd.get_image(frame_name) frame_image = bcd.get_image(frame_name)
if frame_image is not None: if frame_image is not None:
self._layered_images.add_image(frame_image) self._layered_images.add_image (frame_image)
h,w = frame_image.shape[:2]
h,w = frame_image.shape[0:2]
if frame_name is not None: if frame_name is not None:
self._info_label.setText(f'{frame_name} {w}x{h}') self._info_label.setText(f'{frame_name} {w}x{h}')
else: else:

View file

@ -1,47 +1,46 @@
from typing import List from typing import List, Union
import numpy as np import numpy as np
from PyQt6.QtCore import * from PyQt6.QtCore import *
from PyQt6.QtGui import * from PyQt6.QtGui import *
from PyQt6.QtWidgets import * from PyQt6.QtWidgets import *
from ...image import ImageProcessor from ..gui.from_np import QImage_from_np
from ..gui.from_np import QPixmap_from_np
from .QXWidget import QXWidget from .QXWidget import QXWidget
class QXFixedLayeredImages(QXWidget): class QXFixedLayeredImages(QXWidget):
""" """
A widget to show multiple stacked images in fixed area 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): def __init__(self, fixed_width, fixed_height):
super().__init__() super().__init__()
self._fixed_width = fixed_width self._fixed_width = fixed_width
self._fixed_height = fixed_height self._fixed_height = fixed_height
self._qp = QPainter() self._qp = QPainter()
self._pixmaps : List[QPixmap] = [] self._images : List = []
def clear_images(self): def clear_images(self):
self._pixmaps : List[QPixmap] = [] self._images : List = []
self.update() self.update()
def add_image(self, image, name=None): def add_image(self, image, name=None):
""" """
image np.ndarray image QImage
QPixmap QPixmap
np.ndarray of uint8 dtype
all images must have the same aspect ratio
""" """
if isinstance(image, np.ndarray): saved_ref = None
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__}')
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() self.update()
def sizeHint(self): def sizeHint(self):
@ -52,7 +51,6 @@ class QXFixedLayeredImages(QXWidget):
qp = self._qp qp = self._qp
qp.begin(self) qp.begin(self)
#qp.setRenderHint(QPainter.RenderHint.Antialiasing)
qp.setRenderHint(QPainter.RenderHint.SmoothPixmapTransform) qp.setRenderHint(QPainter.RenderHint.SmoothPixmapTransform)
w = self._fixed_width w = self._fixed_width
@ -62,8 +60,9 @@ class QXFixedLayeredImages(QXWidget):
h_half = h /2 h_half = h /2
a = w/h a = w/h
for pixmap in self._pixmaps: for image, _ in self._images:
size = pixmap.size()
size = image.size()
ap = size.width() / size.height() ap = size.width() / size.height()
if ap > a: if ap > a:
@ -75,6 +74,9 @@ class QXFixedLayeredImages(QXWidget):
else: else:
rect = self.rect() 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() qp.end()