DrCyanide / cyanic-sd-krita

A Stable Diffusion plugin for Krita, compatible with A1111 and SD.Next
68 stars 4 forks source link

Cyanic SD - ControlNet preview - Division by zero error #11

Closed Miraihi closed 10 months ago

Miraihi commented 10 months ago

Each time I click "Preview" after choosing the ColtrolNet model and preprocessor, I get the following error. No preview appears. ControlNet still works though.

Exception
Python 3.10.7: C:\Program Files (x86)\Steam\steamapps\common\Krita\krita\bin\krita.exe
Thu Oct 19 19:57:18 2023

A problem occurred in a Python script.  Here is the sequence of
function calls leading up to the error, in the order they occurred.

 C:\Users\Miraihi\AppData\Roaming\krita\pykrita\cyanic\extension_widgets\controlnet.py in <lambda>()
  176         # Preview Preprocessor button
  177         self.preview_preprocessor_btn = QPushButton("Preview")
  178         self.preview_preprocessor_btn.clicked.connect(lambda: self.gen_preview())
  179         self.layout().addWidget(self.preview_preprocessor_btn)
  180 
self = <cyanic.extension_widgets.controlnet.ControlNetUnit object>
self.preview_preprocessor_btn = <PyQt5.QtWidgets.QPushButton object>
self.preview_preprocessor_btn.clicked = <bound PYQT_SIGNAL clicked of QPushButton object>
self.preview_preprocessor_btn.clicked.connect = <built-in method connect of PyQt5.QtCore.pyqtBoundSignal object>
self.gen_preview = <bound method ControlNetUnit.gen_preview of <cya...ension_widgets.controlnet.ControlNetUnit object>>

 C:\Users\Miraihi\AppData\Roaming\krita\pykrita\cyanic\extension_widgets\controlnet.py in gen_preview(self=<cyanic.extension_widgets.controlnet.ControlNetUnit object>)
  432         results = self.cnapi.preview(image_data['input_image'], self.preprocessor, self.variables['preprocessor_resolution'], self.variables['threshold_a'], self.variables['threshold_b'])
  433         kc = KritaController()
  434         kc.results_to_layers(results, self.img_in.size_dict['x'], self.img_in.size_dict['y'], self.img_in.size_dict['w'], self.img_in.size_dict['h'], 'ControlNet Preview')
  435         # NOTE: For OpenPose, results includes {'poses': [{'people': [{'pose_keypoints_2d': [...]}] }]}
  436         # Those pose_keypoints_2d could be used to make a Vector preview of the pose, allowing users to edit the pose more precisely
kc = <cyanic.krita_controller.KritaController object>
kc.results_to_layers = <bound method KritaController.results_to_layers of <cyanic.krita_controller.KritaController object>>
results = {'images': ['iVBORw0KGgoAAAANSUhEUgAAAgAAAAMPCAAAAACGMjJHAAAa...NQMeYQgA4fztmEABvBm7If0LVW4m/+aLcAAAAAElFTkSuQmCC'], 'info': 'Success'}
self = <cyanic.extension_widgets.controlnet.ControlNetUnit object>
self.img_in = <cyanic.widgets.image_in.ImageInWidget object>
self.img_in.size_dict = {'h': 987, 'w': 645, 'x': 303, 'y': 813}

 C:\Users\Miraihi\AppData\Roaming\krita\pykrita\cyanic\krita_controller.py in results_to_layers(self=<cyanic.krita_controller.KritaController object>, results={'images': ['iVBORw0KGgoAAAANSUhEUgAAAgAAAAMPCAAAAACGMjJHAAAa...NQMeYQgA4fztmEABvBm7If0LVW4m/+aLcAAAAAElFTkSuQmCC'], 'info': 'Success'}, x=303, y=813, w=645, h=987, layer_name='ControlNet Preview')
  174                 img_layer_parent.addChildNode(layer, None)
  175                 if img_w != w or img_h != h:
  176                     self.transform_to_width_height(layer, x, y, w, h)
  177                 self.doc.refreshProjection()
  178 
self = <cyanic.krita_controller.KritaController object>
self.transform_to_width_height = <bound method KritaController.transform_to_width...<cyanic.krita_controller.KritaController object>>
layer = <PyKrita.krita.Node object>
x = 303
y = 813
w = 645
h = 987

 C:\Users\Miraihi\AppData\Roaming\krita\pykrita\cyanic\krita_controller.py in transform_to_width_height(self=<cyanic.krita_controller.KritaController object>, layer=<PyKrita.krita.Node object>, x=303, y=813, width=645, height=987)
  304                 self.scale_layer(layer, x, y, width, height)
  305         except Exception as e:
  306             raise Exception('Cyanic SD - %s' % e)
  307             self.scale_layer(layer, x, y, width, height)
  308 
builtinException = <class 'Exception'>
e undefined
Exception: Cyanic SD - division by zero
    __cause__ = None
    __class__ = <class 'Exception'>
    __context__ = ZeroDivisionError('division by zero')
    __delattr__ = <method-wrapper '__delattr__' of Exception object>
    __dict__ = {}
    __dir__ = <built-in method __dir__ of Exception object>
    __doc__ = 'Common base class for all non-exit exceptions.'
    __eq__ = <method-wrapper '__eq__' of Exception object>
    __format__ = <built-in method __format__ of Exception object>
    __ge__ = <method-wrapper '__ge__' of Exception object>
    __getattribute__ = <method-wrapper '__getattribute__' of Exception object>
    __gt__ = <method-wrapper '__gt__' of Exception object>
    __hash__ = <method-wrapper '__hash__' of Exception object>
    __init__ = <method-wrapper '__init__' of Exception object>
    __init_subclass__ = <built-in method __init_subclass__ of type object>
    __le__ = <method-wrapper '__le__' of Exception object>
    __lt__ = <method-wrapper '__lt__' of Exception object>
    __ne__ = <method-wrapper '__ne__' of Exception object>
    __new__ = <built-in method __new__ of type object>
    __reduce__ = <built-in method __reduce__ of Exception object>
    __reduce_ex__ = <built-in method __reduce_ex__ of Exception object>
    __repr__ = <method-wrapper '__repr__' of Exception object>
    __setattr__ = <method-wrapper '__setattr__' of Exception object>
    __setstate__ = <built-in method __setstate__ of Exception object>
    __sizeof__ = <built-in method __sizeof__ of Exception object>
    __str__ = <method-wrapper '__str__' of Exception object>
    __subclasshook__ = <built-in method __subclasshook__ of type object>
    __suppress_context__ = False
    __traceback__ = <traceback object>
    args = ('Cyanic SD - division by zero',)
    with_traceback = <built-in method with_traceback of Exception object>

The above is a description of an error in a Python program.  Here is
the original traceback:

Traceback (most recent call last):
  File "C:\Users\Miraihi\AppData\Roaming\krita\pykrita\cyanic\krita_controller.py", line 302, in transform_to_width_height
    self.use_transform_mask(layer, x, y, width, height)
  File "C:\Users\Miraihi\AppData\Roaming\krita\pykrita\cyanic\krita_controller.py", line 322, in use_transform_mask
    scale_x = width / bounds.width() * 1.0 # 0.4
ZeroDivisionError: division by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\Miraihi\AppData\Roaming\krita\pykrita\cyanic\extension_widgets\controlnet.py", line 178, in <lambda>
    self.preview_preprocessor_btn.clicked.connect(lambda: self.gen_preview())
  File "C:\Users\Miraihi\AppData\Roaming\krita\pykrita\cyanic\extension_widgets\controlnet.py", line 434, in gen_preview
    kc.results_to_layers(results, self.img_in.size_dict['x'], self.img_in.size_dict['y'], self.img_in.size_dict['w'], self.img_in.size_dict['h'], 'ControlNet Preview')
  File "C:\Users\Miraihi\AppData\Roaming\krita\pykrita\cyanic\krita_controller.py", line 176, in results_to_layers
    self.transform_to_width_height(layer, x, y, w, h)
  File "C:\Users\Miraihi\AppData\Roaming\krita\pykrita\cyanic\krita_controller.py", line 306, in transform_to_width_height
    raise Exception('Cyanic SD - %s' % e)
Exception: Cyanic SD - division by zero
Miraihi commented 10 months ago

EDIT: It actually doesn't happen with all preprocessors. But it does with Canny and Lineart at least.

DrCyanide commented 10 months ago

What preprocessor are you trying it out with? I'm pretty sure not all preprocessors have preview options, which could be contributing to the bug (even if I should still be handling it more gracefully than that)

Miraihi commented 10 months ago

Every Lineart preprocessor bugs like that. Also the stock Canny preprocessor. Openpose works fine.

DrCyanide commented 10 months ago

I think this is fixed now, with proper support for the grayscale preview images, but please double check and re-open this if it's not.

I was getting different errors (not Divide by Zero) when I was testing it, but I think I that's because this was reported before ControlNet defaulted to using the canvas if no image was selected, so an empty image would have a height and width of zero.