Skip to content

Instantly share code, notes, and snippets.

@TrevCan
Created November 18, 2025 02:30
Show Gist options
  • Select an option

  • Save TrevCan/65ad5bfad0476438b4124e2291186ae2 to your computer and use it in GitHub Desktop.

Select an option

Save TrevCan/65ad5bfad0476438b4124e2291186ae2 to your computer and use it in GitHub Desktop.
Create dearpygui raw image texture (RGBA), show it, and resize it at will.

Hello. I managed to get away with updating a raw texture with different size by only deleting the texture item and the draw_image item, without deleting the window item. The window itself can be resized without crashing at all, so before re-calling draw_image I resize the window with configure_item. Changing the width or height of the raw texture item always resulted in a crash for me or sometimes in the texture showing completely random data.

setup:

# NOTE: This is not the complete setup. Before any of this, dpg.create_context should be called, as well as dpg.create_viewport()
# And after this code, dpg.setup_dearpygui(), dpg.show_viewport(), dpg.start_dearpygui() or the dpg.render_dearpygui_frame() (only use this function if doing this in a loop)

    with dpg.texture_registry():
        z = np.zeros((700, 700, 4), dtype=np.float32 )
        dpg.add_raw_texture(tag="texture_cropped_optical_tag", width=700, height=700, format=dpg.mvFormat_Float_rgba, default_value=z)

    with dpg.window(label="CROP", tag="cropped_optical_window"):
        dpg.draw_image(tag="draw_ttt", texture_tag="texture_cropped_optical_tag", pmin=[0,0], pmax=[700,700])

my callback function to a button. this is where the deletion and recreation of items is done:

    def button_send_crop_layer(self, sender, app_data, user_data):
        rectangle = self.rectangle(layer_index=user_data["layer_index"])
        startx, starty = rectangle["pmin"][0], rectangle["pmin"][1]
        endx, endy = rectangle["pmax"][0], rectangle["pmax"][1]
        startx = int(startx)
        starty = int(starty)
        endx = int(endx)
        endy = int(endy)
        frame = self.frame.copy()
        print()
        print(startx)
        print(starty)
        print(endx)
        print(endy)
        print()
        cropped_frame = ImageTransformer.frame_crop_frame(frame, startx, starty, endx, endy)
        height, width, _ = cropped_frame.shape

        dpg.delete_item("texture_cropped_optical_tag")
        dpg.delete_item("draw_ttt")
        with dpg.texture_registry():
            #z = np.zeros((height, width, 4), dtype=np.float32)
            z = cropped_frame
            z = ImageTransformer.frame_bgr_to_rgba_normalized(z)
            dpg.add_raw_texture(tag="texture_cropped_optical_tag", width=width, height=height,
                                format=dpg.mvFormat_Float_rgba, default_value=z)

        dpg.configure_item("cropped_optical_window", width=width+10, height=height+10)
        dpg.draw_image(parent="cropped_optical_window" ,tag="draw_ttt", texture_tag="texture_cropped_optical_tag", pmin=[0, 0], pmax=[width, height])
import numpy as np
import cv2
import typing
from typing import Optional
from typing import Tuple
class ImageTransformer:
@staticmethod
def frame_resize(frame, dimensions: Tuple[int, int]):
"""
Resizes to dimensions.
frame is an image frame
dimensions is an integer tuple for (width, height)
"""
return cv2.resize(frame, dsize=dimensions)
@staticmethod
def frame_crop_frame(frame, startx, starty, endx, endy):
"""
Crops frame to coordinate rectangle.
"""
return frame[ starty:endy, startx:endx ]
@staticmethod
def frame_bgr_to_rgba(frame):
"""
Converts BGR frame to RGBA (Red, Green, Blue, Alpha)
uses opencv's cv2.cvtColor
Returns RGBA frame
"""
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
return frame
@staticmethod
def frame_gray_to_rgba(frame):
"""
Converts Gray (binary) frame to RGBA (Red, Green, Blue, Alpha)
uses opencv's cv2.cvtColor
Returns RGBA frame
"""
frame = cv2.cvtColor(frame, cv2.COLOR_GRAY2RGBA)
return frame
@staticmethod
def frame_bgr_to_rgba_normalized(frame):
"""
Converts BGR frame into a normalized (0 to 1 float)
RGBA frame.
This is useful for rendering it in DearPyGUI
"""
video_texture = ImageTransformer.frame_bgr_to_rgba(frame)
video_texture = video_texture.ravel()
video_texture = np.asarray(video_texture, dtype=np.float32)
video_texture = np.true_divide(video_texture, 255.0)
return video_texture
@staticmethod
def frame_gray_to_rgba_normalized(frame):
"""
Converts Gray (binary) frame into a normalized (0 to 1 float)
RGBA frame.
This is useful for rendering it in DearPyGUI
"""
video_texture = ImageTransformer.frame_gray_to_rgba(frame)
video_texture = video_texture.ravel()
video_texture = np.asarray(video_texture, dtype=np.float32)
video_texture = np.true_divide(video_texture, 255.0)
return video_texture
@staticmethod
def frame_bgr_to_gray(frame):
"""
Converts BGR frame to Grayscale.
"""
return cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
@staticmethod
def frame_bgr_to_hsv(frame):
"""
Converts BGR frame to HSV.
"""
return cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
@staticmethod
def frame_gaussian_blur(frame, kernel_size: Optional[Tuple[int, int]] = (5, 5), kernel_deviation: Optional[Tuple[int, int]] = (0, 0) ):
"""
Applies Gaussian Blur to frame.
Optional parameters
"""
return cv2.GaussianBlur(frame, ksize=kernel_size, sigmaX=kernel_deviation[0], sigmaY=kernel_deviation[1])
@staticmethod
def frame_threshold_binary(frame, max_value: Optional[int] = 255, block_size: Optional[int] = 21, c: Optional[int] = 10):
"""
Applies Adaptive Gaussian Threshold to frame,
using the cv2.ADAPTIVE_THRESH_GAUSSIAN_C and
cv2.THRESH_BINARY
"""
return cv2.adaptiveThreshold(
frame,
max_value,
cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY,
block_size,
c)
@staticmethod
def frame_morphology_ex(frame, operation: int = cv2.MORPH_OPEN, iterations: int = 1):
"""
Applies erosion or dilation filters to frame.
"""
kernel = np.ones( (4, 4), np.uint8 )
return cv2.morphologyEx(frame, operation, kernel, iterations=iterations)
@staticmethod
def frame_morph_open(frame, iterations: Optional[int] = 2):
"""
uses cv2.MORPH_OPEN
defaults to 2 iterations
calls frame_morphology_ex
"""
return ImageTransformer.frame_morphology_ex(frame, operation=cv2.MORPH_OPEN, iterations=iterations)
@staticmethod
def frame_morph_close(frame, iterations: Optional[int] = 1):
"""
uses cv2.MORPH_CLOSE
defaults to 1 iteration
calls frame_morphology_ex
"""
return ImageTransformer.frame_morphology_ex(frame, operation=cv2.MORPH_CLOSE, iterations=iterations)
@staticmethod
def in_range_hsv(hsv_frame, low_hsv, high_hsv):
"""
cv2.in_range(hsv_frame, low_hsv, high_hsv)
returns binary mask
"""
return cv2.inRange(hsv_frame, low_hsv, high_hsv)
@staticmethod
def get_binary_mask_polygon(frame_shape, polygon_coordinates):
"""
Returns mask with width and height based on @param frame_shape.
It will set every pixel value within the polygon to 255.
The polygon must be passed as an array of coordinates in
clockwise order or counter clockwise order as per cv2.fillPoly().
[ [x1, y1], [x2, y2], [x3, y3], [x4, y4] ]
"""
if len(polygon_coordinates) < 3:
# this is NOT a polygon!
return None
mask = np.zeros(frame_shape, dtype=np.uint8)
vertices = np.array(polygon_coordinates, dtype=np.int32)
cv2.fillPoly(mask, [vertices], 255)
return mask
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment