diff --git a/README.md b/README.md index 52c480f9..ced411aa 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # BizyAir +- [2024/10/30] 🌩️ BizyAir Segment-Anything nodes has been released. [text_guided_segment-anything](./examples/bizyair_text_guided_segment-anything.json) and [box_point_guided_segment-anything](./examples/bizyair_box_point_guided_segment-anything.json) - [2024/10/24] 🌩️ BizyAir supports stable Diffusion 3.5. [Stable Diffusion 3.5 Text to Image](./examples/bizyair_sd3_5_txt2img.json) - [2024/10/21] 🌩️ BizyAir supports VLModels. We add a tutorial for utilizing the VLM node. [AI Assistant](https://siliconflow.github.io/BizyAir/ai-assistants/introduce.html) - [2024/10/11] 🌩️ BizyAir supports PuLID for Flux. [FLUX PuLID workflow](./examples/bizyair_flux_pulid.json) diff --git a/examples/bizyair_box_point_guided_segment-anything.json b/examples/bizyair_box_point_guided_segment-anything.json new file mode 100644 index 00000000..c492fd6d --- /dev/null +++ b/examples/bizyair_box_point_guided_segment-anything.json @@ -0,0 +1,262 @@ +{ + "last_node_id": 21, + "last_link_id": 18, + "nodes": [ + { + "id": 3, + "type": "PreviewImage", + "pos": { + "0": 1574, + "1": 392, + "2": 0, + "3": 0, + "4": 0, + "5": 0, + "6": 0, + "7": 0, + "8": 0, + "9": 0 + }, + "size": { + "0": 210, + "1": 246 + }, + "flags": {}, + "order": 2, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 17 + } + ], + "outputs": [], + "properties": { + "Node name for S&R": "PreviewImage" + } + }, + { + "id": 12, + "type": "PreviewImage", + "pos": { + "0": 1855, + "1": 389, + "2": 0, + "3": 0, + "4": 0, + "5": 0, + "6": 0, + "7": 0, + "8": 0, + "9": 0 + }, + "size": { + "0": 210, + "1": 246 + }, + "flags": {}, + "order": 4, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 10 + } + ], + "outputs": [], + "properties": { + "Node name for S&R": "PreviewImage" + } + }, + { + "id": 11, + "type": "MaskToImage", + "pos": { + "0": 1810, + "1": 310, + "2": 0, + "3": 0, + "4": 0, + "5": 0, + "6": 0, + "7": 0, + "8": 0, + "9": 0 + }, + "size": { + "0": 264.5999755859375, + "1": 26 + }, + "flags": {}, + "order": 3, + "mode": 0, + "inputs": [ + { + "name": "mask", + "type": "MASK", + "link": 18 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 10 + ], + "slot_index": 0, + "shape": 3 + } + ], + "properties": { + "Node name for S&R": "MaskToImage" + } + }, + { + "id": 20, + "type": "BizyAirSegmentAnythingPointBox", + "pos": { + "0": 1124, + "1": 375, + "2": 0, + "3": 0, + "4": 0, + "5": 0, + "6": 0, + "7": 0, + "8": 0, + "9": 0 + }, + "size": { + "0": 307.80706787109375, + "1": 338 + }, + "flags": {}, + "order": 0, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 17 + ], + "slot_index": 0, + "shape": 3 + }, + { + "name": "MASK", + "type": "MASK", + "links": [ + 18 + ], + "slot_index": 1, + "shape": 3 + } + ], + "properties": { + "Node name for S&R": "BizyAirSegmentAnythingPointBox" + }, + "widgets_values": [ + "clipspace/clipspace-mask-30796.600000023842.png [input]", + false, + "image" + ] + }, + { + "id": 19, + "type": "Note", + "pos": { + "0": 1132, + "1": 160, + "2": 0, + "3": 0, + "4": 0, + "5": 0, + "6": 0, + "7": 0, + "8": 0, + "9": 0 + }, + "size": { + "0": 289.005615234375, + "1": 115.42251586914062 + }, + "flags": {}, + "order": 1, + "mode": 0, + "inputs": [], + "outputs": [], + "properties": {}, + "widgets_values": [ + "SAM EDITOR功能:\n\n可选功能:point模式和box模式\n\n使用步骤:☁️BizyAir Point-Box Guided SAM 节点上右键选择Open in SAM EDITOR,可以通过Select mode按钮切换模式,point模式下通过鼠标左键单击选择抠图区域,box模式下拖动鼠标进行框选\n\n【注意】服务器断开后重连需要重新选择抠图区域,否则会出错\n\nPoint mode按钮: 工作在point mode下,point mode按钮精准控制分割区域,点中区域是想保留得区域(remain)或者要去除得区域(remove)\n\nClear按钮:清除画布上得所有选择抠图区域\n\nUndo按钮:撤销上次选择得抠图区域\n\nCancel:清除画布上得所有选择抠图区域并退出\n\nSave to node: 保存\n\n" + ], + "color": "#432", + "bgcolor": "#653" + } + ], + "links": [ + [ + 10, + 11, + 0, + 12, + 0, + "IMAGE" + ], + [ + 17, + 20, + 0, + 3, + 0, + "IMAGE" + ], + [ + 18, + 20, + 1, + 11, + 0, + "MASK" + ] + ], + "groups": [ + { + "title": "选择抠图区域", + "bounding": [ + 1114, + 309, + 351, + 410 + ], + "color": "#A88", + "font_size": 24 + }, + { + "title": "抠图结果", + "bounding": [ + 1490, + 308, + 642, + 341 + ], + "color": "#b58b2a", + "font_size": 24 + } + ], + "config": {}, + "extra": { + "ds": { + "scale": 1, + "offset": [ + -714.1334533691406, + -26.133377075195312 + ] + } + }, + "version": 0.4 +} diff --git a/js/dialog/sam_edit.js b/js/dialog/sam_edit.js index 0cd5434e..940bfde2 100644 --- a/js/dialog/sam_edit.js +++ b/js/dialog/sam_edit.js @@ -420,7 +420,6 @@ class SAMEditorDialog extends ComfyDialog { alpha_url.searchParams.delete("preview"); alpha_url.searchParams.set("channel", "a"); let mask_image = await loadImage(alpha_url); - // let mask_image = null; const rgb_url = new URL( ComfyApp.clipspace.imgs[ComfyApp.clipspace["selectedIndex"]].src ); @@ -490,21 +489,11 @@ class SAMEditorDialog extends ComfyDialog { setEventHandler(maskCanvas) { const self = this; if (!this.handler_registered) { - // maskCanvas.addEventListener("contextmenu", (event) => { - // event.preventDefault(); - // }); this.element.addEventListener( "wheel", (event) => this.handleWheelEvent(self, event) ); - // this.element.addEventListener( - // "pointermove", - // (event) => this.pointMoveEvent(self, event) - // ); - // this.element.addEventListener( - // "touchmove", - // (event) => this.pointMoveEvent(self, event) - // ); + this.element.addEventListener("dragstart", (event) => { if (event.ctrlKey) { event.preventDefault(); @@ -518,17 +507,14 @@ class SAMEditorDialog extends ComfyDialog { "pointermove", (event) => this.draw_move(self, event) ); - // maskCanvas.addEventListener( - // "touchmove", - // (event) => this.draw_move(self, event) - // ); + maskCanvas.addEventListener("pointerover", (event) => { this.brush.style.display = "block"; }); maskCanvas.addEventListener("pointerleave", (event) => { this.brush.style.display = "none"; }); - // document.addEventListener("pointerup", SAMEditorDialog.handlePointerUp); + maskCanvas.addEventListener( "pointerup", (event) => this.handlePointerUp(self, event) @@ -765,16 +751,12 @@ class SAMEditorDialog extends ComfyDialog { var top = self.endy > self.starty ? self.starty : self.endy var w = Math.abs(self.endx - self.startx) var h = Math.abs(self.endy - self.starty) - // self.maskCtx.save(); + self.maskCtx.rect(left, top, w, h); - // self.maskCtx.fill(); + self.maskCtx.stroke(); self.maskCtx.restore(); } - else if(self.mode === "point"){ - // self.maskCtx.arc(px, py, brush_size, 0, Math.PI * 2, false); - // self.maskCtx.fill(); - } } self.lastx = x; diff --git a/segment_anything.py b/segment_anything.py index 646a327d..de6cc78e 100644 --- a/segment_anything.py +++ b/segment_anything.py @@ -246,7 +246,7 @@ def apply(self, image, is_point): return (img, img_mask) @classmethod - def IS_CHANGED(s, image): + def IS_CHANGED(s, image, is_point): image_path = folder_paths.get_annotated_filepath(image) m = hashlib.sha256() with open(image_path, "rb") as f: @@ -254,7 +254,7 @@ def IS_CHANGED(s, image): return m.digest().hex() @classmethod - def VALIDATE_INPUTS(s, image): + def VALIDATE_INPUTS(s, image, is_point): if not folder_paths.exists_annotated_filepath(image): return "Invalid image file: {}".format(image)