better typehints
faster timeout for webcamera promptserver should not be wrapped in exception
This commit is contained in:
+74
-79
@@ -369,7 +369,7 @@ class Lexicon(metaclass=LexiconMeta):
|
||||
ZOOM = '🔎', "ZOOM"
|
||||
|
||||
@classmethod
|
||||
def _parse(cls, node: dict) -> dict:
|
||||
def _parse(cls, node: dict) -> Dict[str, str]:
|
||||
for cat, entry in node.items():
|
||||
if cat not in ['optional', 'required']:
|
||||
continue
|
||||
@@ -415,7 +415,7 @@ class JOVBaseNode:
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls, prompt:bool=False, extra_png:bool=False, dynprompt:bool=False) -> dict:
|
||||
def INPUT_TYPES(cls, prompt:bool=False, extra_png:bool=False, dynprompt:bool=False) -> Dict[str, str]:
|
||||
data = {
|
||||
"optional": {},
|
||||
"required": {},
|
||||
@@ -685,7 +685,7 @@ def get_node_info(node_data: dict) -> Dict[str, Any]:
|
||||
data[".md"] = md
|
||||
return data
|
||||
|
||||
def deep_merge(d1: dict, d2: dict) -> dict:
|
||||
def deep_merge(d1: dict, d2: dict) -> Dict[str, str]:
|
||||
"""
|
||||
Deep merge multiple dictionaries recursively.
|
||||
|
||||
@@ -734,12 +734,12 @@ class ComfyAPIMessage:
|
||||
|
||||
@classmethod
|
||||
def poll(cls, ident, period=0.01, timeout=3) -> Any:
|
||||
_t = time.monotonic()
|
||||
_t = time.perf_counter()
|
||||
if isinstance(ident, (set, list, tuple, )):
|
||||
ident = ident[0]
|
||||
sid = str(ident)
|
||||
logger.debug(f'sid {sid} -- {cls.MESSAGE}')
|
||||
while not (sid in cls.MESSAGE) and time.monotonic() - _t < timeout:
|
||||
while not (sid in cls.MESSAGE) and time.perf_counter() - _t < timeout:
|
||||
time.sleep(period)
|
||||
|
||||
if not (sid in cls.MESSAGE):
|
||||
@@ -748,95 +748,90 @@ class ComfyAPIMessage:
|
||||
dat = cls.MESSAGE.pop(sid)
|
||||
return dat
|
||||
|
||||
def comfy_message(ident:str, route:str, data:dict) -> None:
|
||||
def comfy_send_message(ident:str, route:str, data:dict) -> None:
|
||||
data['id'] = ident
|
||||
PromptServer.instance.send_sync(route, data)
|
||||
|
||||
try:
|
||||
@PromptServer.instance.routes.get("/jovimetrix")
|
||||
async def jovimetrix_home(request) -> Any:
|
||||
data = template_load('home.html')
|
||||
return web.Response(text=data.template, content_type='text/html')
|
||||
|
||||
@PromptServer.instance.routes.get("/jovimetrix")
|
||||
async def jovimetrix_home(request) -> Any:
|
||||
data = template_load('home.html')
|
||||
return web.Response(text=data.template, content_type='text/html')
|
||||
@PromptServer.instance.routes.get("/jovimetrix/message")
|
||||
async def jovimetrix_message(request) -> Any:
|
||||
return web.json_response(ComfyAPIMessage.MESSAGE)
|
||||
|
||||
@PromptServer.instance.routes.get("/jovimetrix/message")
|
||||
async def jovimetrix_message(request) -> Any:
|
||||
return web.json_response(ComfyAPIMessage.MESSAGE)
|
||||
@PromptServer.instance.routes.post("/jovimetrix/message")
|
||||
async def jovimetrix_message_post(request) -> Any:
|
||||
json_data = await request.json()
|
||||
logger.info(json_data)
|
||||
if (did := json_data.get("id")) is not None:
|
||||
ComfyAPIMessage.MESSAGE[str(did)] = json_data
|
||||
return web.json_response(json_data)
|
||||
return web.json_response({})
|
||||
|
||||
@PromptServer.instance.routes.post("/jovimetrix/message")
|
||||
async def jovimetrix_message_post(request) -> Any:
|
||||
json_data = await request.json()
|
||||
logger.info(json_data)
|
||||
if (did := json_data.get("id")) is not None:
|
||||
ComfyAPIMessage.MESSAGE[str(did)] = json_data
|
||||
return web.json_response(json_data)
|
||||
return web.json_response({})
|
||||
@PromptServer.instance.routes.get("/jovimetrix/config")
|
||||
async def jovimetrix_config(request) -> Any:
|
||||
global JOV_CONFIG, JOV_CONFIG_FILE
|
||||
if len(JOV_CONFIG) == 0:
|
||||
JOV_CONFIG = configLoad(JOV_CONFIG_FILE)
|
||||
return web.json_response(JOV_CONFIG)
|
||||
|
||||
@PromptServer.instance.routes.get("/jovimetrix/config")
|
||||
async def jovimetrix_config(request) -> Any:
|
||||
global JOV_CONFIG, JOV_CONFIG_FILE
|
||||
if len(JOV_CONFIG) == 0:
|
||||
JOV_CONFIG = configLoad(JOV_CONFIG_FILE)
|
||||
return web.json_response(JOV_CONFIG)
|
||||
async def object_info(node_class: str, scheme:str, host: str) -> Any:
|
||||
global COMFYUI_OBJ_DATA
|
||||
if (info := COMFYUI_OBJ_DATA.get(node_class, None)) is None:
|
||||
# look up via the route...
|
||||
url = f"{scheme}://{host}/object_info/{node_class}"
|
||||
|
||||
async def object_info(node_class: str, scheme:str, host: str) -> Any:
|
||||
global COMFYUI_OBJ_DATA
|
||||
if (info := COMFYUI_OBJ_DATA.get(node_class, None)) is None:
|
||||
# look up via the route...
|
||||
url = f"{scheme}://{host}/object_info/{node_class}"
|
||||
|
||||
# Make an asynchronous HTTP request using aiohttp.ClientSession
|
||||
async with ClientSession() as session:
|
||||
try:
|
||||
async with session.get(url) as response:
|
||||
if response.status == 200:
|
||||
info = await response.json()
|
||||
if (data := info.get(node_class, None)) is not None:
|
||||
info = get_node_info(data)
|
||||
else:
|
||||
info = {'.html': f"No data for {node_class}"}
|
||||
COMFYUI_OBJ_DATA[node_class] = info
|
||||
# Make an asynchronous HTTP request using aiohttp.ClientSession
|
||||
async with ClientSession() as session:
|
||||
try:
|
||||
async with session.get(url) as response:
|
||||
if response.status == 200:
|
||||
info = await response.json()
|
||||
if (data := info.get(node_class, None)) is not None:
|
||||
info = get_node_info(data)
|
||||
else:
|
||||
info = {'.html': f"Failed to get docs {node_class}, status: {response.status}"}
|
||||
logger.error(info)
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to get docs {node_class}")
|
||||
logger.exception(e)
|
||||
info = {'.html': f"Failed to get docs {node_class}\n{e}"}
|
||||
info = {'.html': f"No data for {node_class}"}
|
||||
COMFYUI_OBJ_DATA[node_class] = info
|
||||
else:
|
||||
info = {'.html': f"Failed to get docs {node_class}, status: {response.status}"}
|
||||
logger.error(info)
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to get docs {node_class}")
|
||||
logger.exception(e)
|
||||
info = {'.html': f"Failed to get docs {node_class}\n{e}"}
|
||||
|
||||
return info
|
||||
return info
|
||||
|
||||
@PromptServer.instance.routes.get("/jovimetrix/doc")
|
||||
async def jovimetrix_doc(request) -> Any:
|
||||
@PromptServer.instance.routes.get("/jovimetrix/doc")
|
||||
async def jovimetrix_doc(request) -> Any:
|
||||
|
||||
for node_class in NODE_CLASS_MAPPINGS.keys():
|
||||
if COMFYUI_OBJ_DATA.get(node_class, None) is None:
|
||||
COMFYUI_OBJ_DATA[node_class] = await object_info(node_class, request.scheme, request.host)
|
||||
|
||||
node = NODE_DISPLAY_NAME_MAPPINGS[node_class]
|
||||
fname = node.split(" (JOV)")[0]
|
||||
path = Path(JOV_INTERNAL_DOC.replace("{name}", fname))
|
||||
path.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
if JOV_INTERNAL:
|
||||
if (md := COMFYUI_OBJ_DATA[node_class].get('.md', None)) is not None:
|
||||
with open(str(path / f"{fname}.md"), "w", encoding='utf-8') as f:
|
||||
f.write(md)
|
||||
|
||||
with open(str(path / f"{fname}.html"), "w", encoding='utf-8') as f:
|
||||
f.write(COMFYUI_OBJ_DATA[node_class]['.html'])
|
||||
|
||||
return web.json_response(COMFYUI_OBJ_DATA)
|
||||
|
||||
@PromptServer.instance.routes.get("/jovimetrix/doc/{node}")
|
||||
async def jovimetrix_doc_node_comfy(request) -> Any:
|
||||
node_class = request.match_info.get('node')
|
||||
for node_class in NODE_CLASS_MAPPINGS.keys():
|
||||
if COMFYUI_OBJ_DATA.get(node_class, None) is None:
|
||||
COMFYUI_OBJ_DATA[node_class] = await object_info(node_class, request.scheme, request.host)
|
||||
return web.Response(text=COMFYUI_OBJ_DATA[node_class]['.html'], content_type='text/html')
|
||||
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
node = NODE_DISPLAY_NAME_MAPPINGS[node_class]
|
||||
fname = node.split(" (JOV)")[0]
|
||||
path = Path(JOV_INTERNAL_DOC.replace("{name}", fname))
|
||||
path.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
if JOV_INTERNAL:
|
||||
if (md := COMFYUI_OBJ_DATA[node_class].get('.md', None)) is not None:
|
||||
with open(str(path / f"{fname}.md"), "w", encoding='utf-8') as f:
|
||||
f.write(md)
|
||||
|
||||
with open(str(path / f"{fname}.html"), "w", encoding='utf-8') as f:
|
||||
f.write(COMFYUI_OBJ_DATA[node_class]['.html'])
|
||||
|
||||
return web.json_response(COMFYUI_OBJ_DATA)
|
||||
|
||||
@PromptServer.instance.routes.get("/jovimetrix/doc/{node}")
|
||||
async def jovimetrix_doc_node_comfy(request) -> Any:
|
||||
node_class = request.match_info.get('node')
|
||||
if COMFYUI_OBJ_DATA.get(node_class, None) is None:
|
||||
COMFYUI_OBJ_DATA[node_class] = await object_info(node_class, request.scheme, request.host)
|
||||
return web.Response(text=COMFYUI_OBJ_DATA[node_class]['.html'], content_type='text/html')
|
||||
|
||||
# ==============================================================================
|
||||
# === SUPPORT ===
|
||||
|
||||
+20
-20
@@ -7,7 +7,7 @@ import sys
|
||||
import math
|
||||
import random
|
||||
from enum import Enum
|
||||
from typing import Any, Tuple
|
||||
from typing import Any, Dict, Tuple
|
||||
from collections import Counter
|
||||
|
||||
import torch
|
||||
@@ -19,7 +19,7 @@ from comfy.utils import ProgressBar
|
||||
|
||||
from .. import JOV_TYPE_ANY, JOV_TYPE_FULL, JOV_TYPE_NUMBER, JOV_TYPE_VECTOR, \
|
||||
Lexicon, JOVBaseNode, \
|
||||
comfy_message, deep_merge, parse_reset
|
||||
comfy_send_message, deep_merge, parse_reset
|
||||
|
||||
from ..sup.util import EnumConvertType, EnumSwizzle, \
|
||||
parse_dynamic, parse_param, parse_value, vector_swap, zip_longest_fill
|
||||
@@ -206,7 +206,7 @@ Split an input into separate bits. `BOOL`, `INT` and `FLOAT` use their numbers,
|
||||
image.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -234,7 +234,7 @@ Perform single function operations like absolute value, mean, median, mode, magn
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -336,7 +336,7 @@ Execute binary operations like addition, subtraction, multiplication, division,
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
names_convert = EnumConvertType._member_names_[:10]
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
@@ -478,7 +478,7 @@ Evaluates two inputs (A and B) with a specified comparison operators and optiona
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -600,7 +600,7 @@ Additionally, you can specify the easing function (EASE) and the desired output
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
names_convert = EnumConvertType._member_names_[:10]
|
||||
d = deep_merge(d, {
|
||||
@@ -685,7 +685,7 @@ Manipulate strings through filtering
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -750,7 +750,7 @@ Swap components between two vectors based on specified swizzle patterns and valu
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
names_convert = EnumConvertType._member_names_[3:10]
|
||||
d = deep_merge(d, {
|
||||
@@ -805,7 +805,7 @@ A timer and frame counter, emitting pulses or signals based on time intervals. I
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -880,7 +880,7 @@ A timer and frame counter, emitting pulses or signals based on time intervals. I
|
||||
pbar.update_absolute(idx)
|
||||
|
||||
if batch < 2:
|
||||
comfy_message(ident, "jovi-tick", {"i": self.__frame})
|
||||
comfy_send_message(ident, "jovi-tick", {"i": self.__frame})
|
||||
return (results.frame, results.lin, results.fixed, results.trigger, results.batch,)
|
||||
|
||||
class ValueNode(JOVBaseNode):
|
||||
@@ -896,7 +896,7 @@ Supplies raw or default values for various data types, supporting vector input w
|
||||
UPDATE = False
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
|
||||
typ = EnumConvertType._member_names_
|
||||
@@ -1012,7 +1012,7 @@ Produce waveforms like sine, square, or sawtooth with adjustable frequency, ampl
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -1066,7 +1066,7 @@ Outputs a VEC2 or VEC2INT.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -1104,7 +1104,7 @@ Outputs a VEC2 or VEC2INT.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -1142,7 +1142,7 @@ Outputs a VEC3 or VEC3INT.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -1183,7 +1183,7 @@ Outputs a VEC3 or VEC3INT.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -1224,7 +1224,7 @@ Outputs a VEC4 or VEC4INT.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -1268,7 +1268,7 @@ Outputs a VEC4 or VEC4INT.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -1309,7 +1309,7 @@ class ParameterNode(JOVBaseNode):
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
|
||||
+18
-18
@@ -4,7 +4,7 @@ Composition
|
||||
"""
|
||||
|
||||
from enum import Enum
|
||||
from typing import Any, List, Tuple
|
||||
from typing import Any, Dict, List, Tuple
|
||||
|
||||
import cv2
|
||||
import torch
|
||||
@@ -78,7 +78,7 @@ Enhance and modify images with various effects such as blurring, sharpening, col
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -226,7 +226,7 @@ Combine two input images using various blending modes, such as normal, screen, m
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -315,7 +315,7 @@ Simulate color blindness effects on images. You can select various types of colo
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -352,7 +352,7 @@ Adjust the color scheme of one image to match another with the Color Match Node.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -440,7 +440,7 @@ The top-k colors ordered from most->least used as a strip, tonal palette and 3D
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -498,7 +498,7 @@ Generate a color harmony based on the selected scheme. Supported schemes include
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -537,7 +537,7 @@ Extract a portion of an input image or resize it. It supports various cropping m
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -601,7 +601,7 @@ Create masks based on specific color ranges within an image. Specify the color r
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -646,7 +646,7 @@ Combine multiple input images into a single image by summing their pixel values.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -689,7 +689,7 @@ Remaps an input image using a gradient lookup table (LUT). The gradient image wi
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -741,7 +741,7 @@ Combines individual color channels (red, green, blue) along with an optional mas
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -823,7 +823,7 @@ Takes an input image and splits it into its individual color channels (red, gree
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -851,7 +851,7 @@ Swap pixel values between two input images based on specified channel swizzle op
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -916,7 +916,7 @@ Merge multiple input images into a single composite image by stacking them along
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -960,7 +960,7 @@ Define a range and apply it to an image for segmentation and feature extraction.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -1003,7 +1003,7 @@ Apply various geometric transformations to images, including translation, rotati
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -1101,7 +1101,7 @@ The Histogram Node generates a histogram representation of the input image, show
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
|
||||
+6
-7
@@ -3,13 +3,12 @@ Jovimetrix - http://www.github.com/amorano/jovimetrix
|
||||
Creation
|
||||
"""
|
||||
|
||||
from typing import Tuple
|
||||
from typing import Dict, Tuple
|
||||
|
||||
import torch
|
||||
import numpy as np
|
||||
from PIL import ImageFont
|
||||
from skimage.filters import gaussian
|
||||
from loguru import logger
|
||||
|
||||
from comfy.utils import ProgressBar
|
||||
|
||||
@@ -50,7 +49,7 @@ Generate a constant image or mask of a specified size and color. It can be used
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -97,7 +96,7 @@ Create n-sided polygons. These shapes can be customized by adjusting parameters
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -168,7 +167,7 @@ Generates false perception 3D images from 2D input. Set tile divisions, noise, g
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -214,7 +213,7 @@ class StereoscopicNode(JOVBaseNode):
|
||||
Simulates depth perception in images by generating stereoscopic views. It accepts an optional input image for color matte. Adjust baseline and focal length for customized depth effects.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -252,7 +251,7 @@ Generates images containing text based on parameters such as font, size, alignme
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
|
||||
+7
-7
@@ -5,7 +5,7 @@ Creation
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Any, Tuple
|
||||
from typing import Any, Dict, Tuple
|
||||
|
||||
import torch
|
||||
from loguru import logger
|
||||
@@ -19,7 +19,7 @@ from comfy.utils import ProgressBar
|
||||
|
||||
from .. import JOV_TYPE_IMAGE, \
|
||||
Lexicon, JOVImageNode, \
|
||||
comfy_message, deep_merge
|
||||
comfy_send_message, deep_merge
|
||||
|
||||
from ..sup.util import EnumConvertType, \
|
||||
parse_param, parse_value
|
||||
@@ -86,7 +86,7 @@ class GLSLNodeBase(JOVImageNode):
|
||||
CATEGORY = f"JOVIMETRIX 🔺🟩🔵/GLSL"
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -122,7 +122,7 @@ class GLSLNodeBase(JOVImageNode):
|
||||
self.__glsl.vertex = getattr(self, 'VERTEX', kw.pop(Lexicon.PROG_VERT, None))
|
||||
self.__glsl.fragment = getattr(self, 'FRAGMENT', kw.pop(Lexicon.PROG_FRAG, None))
|
||||
except CompileException as e:
|
||||
comfy_message(ident, "jovi-glsl-error", {"id": ident, "e": str(e)})
|
||||
comfy_send_message(ident, "jovi-glsl-error", {"id": ident, "e": str(e)})
|
||||
logger.error(self.NAME)
|
||||
logger.error(e)
|
||||
return
|
||||
@@ -169,7 +169,7 @@ class GLSLNodeBase(JOVImageNode):
|
||||
img = image_scalefit(img, w, h, mode, sample)
|
||||
images.append(cv2tensor_full(img, matte))
|
||||
self.__delta += step
|
||||
comfy_message(ident, "jovi-glsl-time", {"id": ident, "t": self.__delta})
|
||||
comfy_send_message(ident, "jovi-glsl-time", {"id": ident, "t": self.__delta})
|
||||
pbar.update_absolute(idx)
|
||||
return [torch.stack(i) for i in zip(*images)]
|
||||
|
||||
@@ -181,7 +181,7 @@ Execute custom GLSL (OpenGL Shading Language) fragment shaders to generate image
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
opts = d.get('optional', {})
|
||||
opts.update({
|
||||
@@ -203,7 +203,7 @@ class GLSLNodeDynamic(GLSLNodeBase):
|
||||
PARAM = None
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
original_params = super().INPUT_TYPES()
|
||||
opts = original_params.get('optional', {})
|
||||
opts.update({
|
||||
|
||||
+5
-7
@@ -7,12 +7,10 @@ Device -- MIDI
|
||||
type 2 (asynchronous): each track is independent of the others
|
||||
"""
|
||||
|
||||
from typing import Tuple
|
||||
from typing import Dict, Tuple
|
||||
from math import isclose
|
||||
from queue import Queue
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from comfy.utils import ProgressBar
|
||||
|
||||
from .. import JOVBaseNode, Lexicon, deep_merge
|
||||
@@ -50,7 +48,7 @@ Processes MIDI messages received from an external MIDI controller or device. It
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -83,7 +81,7 @@ Captures MIDI messages from an external MIDI device or controller. It monitors M
|
||||
CHANGED = False
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -154,7 +152,7 @@ Provides advanced filtering capabilities for MIDI messages based on various crit
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -259,7 +257,7 @@ Filter MIDI messages based on various criteria, including MIDI mode (such as not
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
|
||||
@@ -6,7 +6,7 @@ Device -- WEBCAM, REMOTE URLS, SPOUT
|
||||
import sys
|
||||
import time
|
||||
import uuid
|
||||
from typing import Tuple
|
||||
from typing import Dict, Tuple
|
||||
from enum import Enum
|
||||
|
||||
import cv2
|
||||
@@ -76,7 +76,7 @@ Capture frames from various sources such as URLs, cameras, monitors, windows, or
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
|
||||
if cls.CAMERAS is None:
|
||||
@@ -297,7 +297,7 @@ Sends frames to a specified route, typically for live streaming or recording pur
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -368,7 +368,7 @@ Sends frames to a specified Spout receiver application for real-time video shari
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
|
||||
@@ -11,7 +11,7 @@ import random
|
||||
from enum import Enum
|
||||
from pathlib import Path
|
||||
from itertools import zip_longest
|
||||
from typing import Any, List, Literal, Tuple
|
||||
from typing import Any, Dict, List, Literal, Tuple
|
||||
|
||||
import torch
|
||||
import numpy as np
|
||||
@@ -22,7 +22,7 @@ from comfy.utils import ProgressBar
|
||||
from nodes import interrupt_processing
|
||||
|
||||
from ... import JOV_TYPE_ANY, ROOT, Lexicon, JOVBaseNode, deep_merge, \
|
||||
comfy_message, parse_reset
|
||||
comfy_send_message, parse_reset
|
||||
|
||||
from ...sup.util import EnumConvertType, parse_dynamic, parse_param
|
||||
|
||||
@@ -70,7 +70,7 @@ Processes a batch of data based on the selected mode, such as merging, picking,
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -239,7 +239,7 @@ class QueueBaseNode(JOVBaseNode):
|
||||
return float('nan')
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -373,7 +373,7 @@ class QueueBaseNode(JOVBaseNode):
|
||||
# make sure we have more to process if are a single fire queue
|
||||
stop = parse_param(kw, Lexicon.STOP, EnumConvertType.BOOLEAN, False)[0]
|
||||
if stop and self.__index >= self.__len:
|
||||
comfy_message(ident, "jovi-queue-done", self.status)
|
||||
comfy_send_message(ident, "jovi-queue-done", self.status)
|
||||
interrupt_processing()
|
||||
return self.__previous, self.__q, self.__current, self.__index_last+1, self.__len
|
||||
|
||||
@@ -430,7 +430,7 @@ class QueueBaseNode(JOVBaseNode):
|
||||
self.__index += 1
|
||||
|
||||
self.__previous = data
|
||||
comfy_message(ident, "jovi-queue-ping", self.status)
|
||||
comfy_send_message(ident, "jovi-queue-ping", self.status)
|
||||
if stop and batched:
|
||||
interrupt_processing()
|
||||
return data, self.__q, self.__current, self.__index, self.__len, self.__index == self.__index_last or batched
|
||||
@@ -479,7 +479,7 @@ Manage a queue of specific items: media files. Supports various image and video
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
|
||||
@@ -5,7 +5,7 @@ Utility
|
||||
|
||||
import io
|
||||
import json
|
||||
from typing import Any, Tuple
|
||||
from typing import Any, Dict, Tuple
|
||||
|
||||
import torch
|
||||
import numpy as np
|
||||
@@ -137,7 +137,7 @@ Visualize a series of data points over time. It accepts a dynamic number of valu
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -218,7 +218,7 @@ Exports and Displays immediate information about images.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
|
||||
+7
-7
@@ -7,7 +7,7 @@ import os
|
||||
import json
|
||||
from uuid import uuid4
|
||||
from pathlib import Path
|
||||
from typing import Any, Tuple
|
||||
from typing import Any, Dict, Tuple
|
||||
|
||||
import torch
|
||||
import numpy as np
|
||||
@@ -22,7 +22,7 @@ from nodes import interrupt_processing
|
||||
|
||||
from ... import JOV_TYPE_ANY, JOV_TYPE_IMAGE, \
|
||||
Lexicon, JOVBaseNode, ComfyAPIMessage, TimedOutException, \
|
||||
comfy_message, deep_merge
|
||||
comfy_send_message, deep_merge
|
||||
|
||||
from ...sup.util import EnumConvertType, path_next, parse_param, \
|
||||
zip_longest_fill
|
||||
@@ -71,7 +71,7 @@ Introduce pauses in the workflow that accept an optional input to pass through a
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -94,7 +94,7 @@ Introduce pauses in the workflow that accept an optional input to pass through a
|
||||
if delay < 0:
|
||||
delay = JOV_DELAY_MAX
|
||||
if delay > JOV_DELAY_MIN:
|
||||
comfy_message(ident, "jovi-delay-user", {"id": ident, "timeout": delay})
|
||||
comfy_send_message(ident, "jovi-delay-user", {"id": ident, "timeout": delay})
|
||||
# enable = parse_param(kw, Lexicon.ENABLE, EnumConvertType.BOOLEAN, True)
|
||||
|
||||
step = 1
|
||||
@@ -125,7 +125,7 @@ Responsible for saving images or animations to disk. It supports various output
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
@@ -235,7 +235,7 @@ Routes the input data from the optional input ports to the output port, preservi
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES()
|
||||
e = {
|
||||
"optional": {
|
||||
@@ -263,7 +263,7 @@ Save the output image along with its metadata to the specified path. Supports sa
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
def INPUT_TYPES(cls) -> Dict[str, str]:
|
||||
d = super().INPUT_TYPES(True, True)
|
||||
d = deep_merge(d, {
|
||||
"optional": {
|
||||
|
||||
+3
-18
@@ -6,12 +6,11 @@
|
||||
Copyright 2023 Alexander Morano (Joviex)
|
||||
"""
|
||||
|
||||
import io
|
||||
from io import BytesIO
|
||||
import math
|
||||
import base64
|
||||
import requests
|
||||
from enum import Enum
|
||||
from io import BytesIO
|
||||
from typing import List, Tuple, Union
|
||||
|
||||
import cv2
|
||||
@@ -19,8 +18,6 @@ import torch
|
||||
import numpy as np
|
||||
from PIL import Image, ImageOps
|
||||
|
||||
from loguru import logger
|
||||
|
||||
# ==============================================================================
|
||||
# === GLOBAL ===
|
||||
# ==============================================================================
|
||||
@@ -54,11 +51,6 @@ TYPE_VECTOR = Union[TYPE_IMAGE, TYPE_PIXEL]
|
||||
# === ENUMERATION ===
|
||||
# ==============================================================================
|
||||
|
||||
class EnumGrayscaleCrunch(Enum):
|
||||
LOW = 0
|
||||
HIGH = 1
|
||||
MEAN = 2
|
||||
|
||||
class EnumImageType(Enum):
|
||||
GRAYSCALE = 0
|
||||
RGB = 10
|
||||
@@ -66,10 +58,6 @@ class EnumImageType(Enum):
|
||||
BGR = 30
|
||||
BGRA = 40
|
||||
|
||||
class EnumIntFloat(Enum):
|
||||
FLOAT = 0
|
||||
INT = 1
|
||||
|
||||
# ==============================================================================
|
||||
# === CONVERSION ===
|
||||
# ==============================================================================
|
||||
@@ -92,13 +80,13 @@ def b64_2_tensor(base64str: str) -> torch.Tensor:
|
||||
def b64_2_pil(base64_string):
|
||||
prefix, base64_data = base64_string.split(",", 1)
|
||||
image_data = base64.b64decode(base64_data)
|
||||
image_stream = io.BytesIO(image_data)
|
||||
image_stream = BytesIO(image_data)
|
||||
return Image.open(image_stream)
|
||||
|
||||
def b64_2_cv(base64_string) -> TYPE_IMAGE:
|
||||
_, data = base64_string.split(",", 1)
|
||||
data = base64.b64decode(data)
|
||||
data = io.BytesIO(data)
|
||||
data = BytesIO(data)
|
||||
data = Image.open(data)
|
||||
data = np.array(data)
|
||||
return cv2.cvtColor(data, cv2.COLOR_RGB2BGR)
|
||||
@@ -386,7 +374,6 @@ def image_load(url: str) -> Tuple[TYPE_IMAGE, TYPE_IMAGE]:
|
||||
raise ValueError(f"{url} could not be loaded.")
|
||||
|
||||
img = image_normalize(img)
|
||||
# logger.debug(f"load image {url}: {img.ndim} {img.shape}")
|
||||
if img.ndim == 3:
|
||||
if img.shape[2] == 4:
|
||||
img = cv2.cvtColor(img, cv2.COLOR_RGBA2BGRA)
|
||||
@@ -396,7 +383,6 @@ def image_load(url: str) -> Tuple[TYPE_IMAGE, TYPE_IMAGE]:
|
||||
img = np.expand_dims(img, -1)
|
||||
|
||||
except Exception:
|
||||
logger.debug(f"load image fallback to PIL {url}")
|
||||
try:
|
||||
img = Image.open(url)
|
||||
img = ImageOps.exif_transpose(img)
|
||||
@@ -404,7 +390,6 @@ def image_load(url: str) -> Tuple[TYPE_IMAGE, TYPE_IMAGE]:
|
||||
if img.dtype != np.uint8:
|
||||
img = np.clip(np.array(img * 255), 0, 255).astype(dtype=np.uint8)
|
||||
except Exception as e:
|
||||
# logger.error(str(e))
|
||||
raise Exception(f"Error loading image: {e}")
|
||||
|
||||
if img is None:
|
||||
|
||||
+5
-5
@@ -10,16 +10,16 @@ import cv2
|
||||
import torch
|
||||
import numpy as np
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from . import TYPE_IMAGE, TYPE_PIXEL, TYPE_fCOORD2D, \
|
||||
EnumImageType, \
|
||||
from . import \
|
||||
TYPE_IMAGE, TYPE_PIXEL, \
|
||||
TYPE_fCOORD2D, EnumImageType, \
|
||||
image_convert, image_mask_add, image_matte, image_minmax, bgr2image, \
|
||||
cv2tensor, image2bgr, tensor2cv
|
||||
|
||||
from .compose import image_blend, image_crop_center
|
||||
|
||||
from .channel import EnumPixelSwizzle, \
|
||||
from .channel import \
|
||||
EnumPixelSwizzle, \
|
||||
channel_solid
|
||||
|
||||
# ==============================================================================
|
||||
|
||||
+10
-3
@@ -15,10 +15,8 @@ from sklearn.cluster import KMeans
|
||||
from daltonlens import simulate
|
||||
from blendmodes.blend import BlendType
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from . import TYPE_IMAGE, TYPE_PIXEL, \
|
||||
EnumGrayscaleCrunch, EnumImageType, EnumIntFloat, \
|
||||
EnumImageType, \
|
||||
bgr2hsv, hsv2bgr, image_convert, image_mask, image_mask_add
|
||||
|
||||
from .compose import image_blend
|
||||
@@ -33,6 +31,15 @@ TYPE_LUT = Tuple[int, int, int, int]
|
||||
# === ENUMERATION ===
|
||||
# ==============================================================================
|
||||
|
||||
class EnumIntFloat(Enum):
|
||||
FLOAT = 0
|
||||
INT = 1
|
||||
|
||||
class EnumGrayscaleCrunch(Enum):
|
||||
LOW = 0
|
||||
HIGH = 1
|
||||
MEAN = 2
|
||||
|
||||
class EnumColorMap(Enum):
|
||||
AUTUMN = cv2.COLORMAP_AUTUMN
|
||||
BONE = cv2.COLORMAP_BONE
|
||||
|
||||
+5
-5
@@ -10,7 +10,7 @@ import json
|
||||
import time
|
||||
import array
|
||||
import threading
|
||||
from typing import Any, List, Tuple
|
||||
from typing import Any, Dict, List, Tuple
|
||||
from itertools import repeat
|
||||
from configparser import ConfigParser
|
||||
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
||||
@@ -97,7 +97,7 @@ def monitor_capture(monitor:int=0, tlwh:Tuple[int, int, int, int]=None, width:in
|
||||
img = cv2.resize(img, (width, height))
|
||||
return img
|
||||
|
||||
def monitor_list() -> dict:
|
||||
def monitor_list() -> Dict[str, str]:
|
||||
if JOV_DOCKERENV:
|
||||
return {}
|
||||
ret = {}
|
||||
@@ -105,7 +105,7 @@ def monitor_list() -> dict:
|
||||
ret = {i:v for i, v in enumerate(sct.monitors)}
|
||||
return ret
|
||||
|
||||
def window_list() -> dict:
|
||||
def window_list() -> Dict[str, str]:
|
||||
return {}
|
||||
|
||||
if sys.platform.startswith('win'):
|
||||
@@ -114,7 +114,7 @@ if sys.platform.startswith('win'):
|
||||
import win32ui
|
||||
from ctypes import windll
|
||||
|
||||
def window_list() -> dict:
|
||||
def window_list() -> Dict[str, str]:
|
||||
_windows = {}
|
||||
def window_enum_handler(hwnd, ctx) -> None:
|
||||
if win32gui.IsWindowVisible(hwnd):
|
||||
@@ -191,7 +191,7 @@ elif sys.platform.startswith('darwin'):
|
||||
|
||||
return None
|
||||
|
||||
def window_list() -> dict:
|
||||
def window_list() -> Dict[str, str]:
|
||||
_windows = {}
|
||||
window_list = Quartz.CGWindowListCopyWindowInfo(
|
||||
Quartz.kCGWindowListOptionOnScreenOnly | Quartz.kCGWindowListExcludeDesktopElements,
|
||||
|
||||
Reference in New Issue
Block a user