Refactor and clean up codebase by removing unused functions and reorganizing imports
- Removed unused model keys and functions from properties.py. - Deleted projection.py as its functions were no longer needed. - Cleaned up model_catalog.py by removing unused model directory function. - Updated imports in various test files to reflect new module structure. - Removed deprecated test cases related to image editing tools. - Added new tests for ONNX runtime provider selection logic.
This commit is contained in:
10
AGENTS.md
10
AGENTS.md
@@ -12,6 +12,16 @@
|
|||||||
- 复用来自 `common` 的函数,避免重复造轮子
|
- 复用来自 `common` 的函数,避免重复造轮子
|
||||||
- 确保文件名/文件夹名和内容边界一致
|
- 确保文件名/文件夹名和内容边界一致
|
||||||
|
|
||||||
|
## 全面整理代码
|
||||||
|
|
||||||
|
当用户说「全面整理代码」时,依据本文件规范,直接执行以下整理:
|
||||||
|
|
||||||
|
- 按业务职责梳理代码结构与命名;简单功能用单文件,复杂 Operator 功能包统一以 `operators.py` 为入口,`__init__.py` 负责导出与注册清单。
|
||||||
|
- 沿真实调用链清理无用代码,不把仅有测试引用当作业务用途;查证动态调用、框架回调和注册入口后再删除。
|
||||||
|
- 精简测试,保留有效行为覆盖,使测试名称、归属与功能对应,并检查状态隔离。
|
||||||
|
- 同步整理 `tools/node_assets`、`docs/internals` 和相关引用,使名称、说明与实际实现一致。本触发指令包含内部文档整理。
|
||||||
|
- 保留已有的其他修改和有效功能,运行全量测试并确认正常退出,检查旧引用与最终差异,简要报告调整及验证结果;不构建文档或产物。
|
||||||
|
|
||||||
## 查询文档
|
## 查询文档
|
||||||
|
|
||||||
下列是重要文档
|
下列是重要文档
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ flowchart TD
|
|||||||
|
|
||||||
### 判断是否交给 Blender
|
### 判断是否交给 Blender
|
||||||
|
|
||||||
`operators/clipboard_image/__init__.py` 注册 `TrackNativeCopy`、`PasteClipboardImage` 和 3D View、Node Editor 快捷键。`TrackNativeCopy` 记录 Blender Copy 时的系统剪贴板变化标记;粘贴时若标记没有变化,`PasteClipboardImage` 返回 `PASS_THROUGH`,让 Blender 继续处理对象或节点粘贴。
|
`operators/clipboard_image/operators.py` 定义 `TrackNativeCopy`、`PasteClipboardImage` 和 3D View、Node Editor 快捷键。`TrackNativeCopy` 记录 Blender Copy 时的系统剪贴板变化标记;粘贴时若标记没有变化,`PasteClipboardImage` 返回 `PASS_THROUGH`,让 Blender 继续处理对象或节点粘贴。
|
||||||
|
|
||||||
同一文件随后调用 `actions.target_for_context()` 判断当前编辑器是否支持图片落点。
|
同一文件随后调用 `actions.target_for_context()` 判断当前编辑器是否支持图片落点。
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Plane 转换
|
# Plane 转换
|
||||||
|
|
||||||
`operators/convert_to_plane/conversion.py` 提供 `ConvertToPlane`、`ConvertToDepthPlane` 与 `GenerateDepthPlane`。对象和材质导入位于 `object.py`,基础矩形网格位于 `image_plane.py`。
|
`operators/convert_to_plane/operators.py` 提供 `ConvertToPlane`、`ConvertToDepthPlane` 与 `GenerateDepthPlane`。对象和材质导入位于 `object.py`,基础矩形网格位于 `image_plane.py`。
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
flowchart TD
|
flowchart TD
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Cutout
|
# Cutout
|
||||||
|
|
||||||
Cutout 在静态 Image Empty 上圈定 Selection,按轮廓创建 Flat、Solid、Depth Solid 或 Depth Balloon。入口位于 `operators/cutout_tool/main.py`,菜单与采样级别映射位于 `interaction.py`,标识和资产对应关系位于 `shape.py`。
|
Cutout 在静态 Image Empty 上圈定 Selection,按轮廓创建 Flat、Solid、Depth Solid 或 Depth Balloon。入口位于 `operators/cutout_tool/operators.py`,菜单与采样级别映射位于 `interaction.py`,标识和资产对应关系位于 `shape.py`。
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
flowchart TD
|
flowchart TD
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Frame 多图合成
|
# Frame 多图合成
|
||||||
|
|
||||||
`operators/image_edit_tool/frame.py` 定义 `FrameImages`、`FrameTool` 和工具激活入口。Frame 将选中的静态 Image Empty 按当前视图合成为一张图片。
|
`operators/frame_tool.py` 定义 `FrameImages` 和 `FrameTool`。Frame 将选中的静态 Image Empty 按当前视图合成为一张图片。
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
flowchart TD
|
flowchart TD
|
||||||
|
|||||||
@@ -6,10 +6,10 @@
|
|||||||
| `operators/clipboard_image/` | [剪贴板图片](clipboard-image.md) |
|
| `operators/clipboard_image/` | [剪贴板图片](clipboard-image.md) |
|
||||||
| `operators/convert_to_plane/` | [Plane 与 Depth Plane](convert-to-plane.md) |
|
| `operators/convert_to_plane/` | [Plane 与 Depth Plane](convert-to-plane.md) |
|
||||||
| `operators/cutout_tool/` | [Cutout](cutout-tool.md) |
|
| `operators/cutout_tool/` | [Cutout](cutout-tool.md) |
|
||||||
| `operators/image_edit_tool/frame.py` | [Frame 多图合成](frame.md) |
|
| `operators/frame_tool.py` | [Frame 多图合成](frame.md) |
|
||||||
| `operators/image_edit_tool/mask.py` | [Mask Alpha 编辑](mask.md) |
|
| `operators/mask_tool.py` | [Mask Alpha 编辑](mask.md) |
|
||||||
| `operators/image_edit_tool/rectify.py` | [Rectify 透视校正](rectify.md) |
|
| `operators/rectify_tool.py` | [Rectify 透视校正](rectify.md) |
|
||||||
| `operators/remove_background.py` | [Remove Background](remove-background.md) |
|
| `operators/remove_background.py` | [Remove Background](remove-background.md) |
|
||||||
| `operators/upscale.py` | [Upscale](upscale.md) |
|
| `operators/upscale.py` | [Upscale](upscale.md) |
|
||||||
|
|
||||||
类型在 `operators/__init__.py` 和扩展 `__init__.py` 汇总注册。AI Operator 使用普通字典提交任务,并在主线程响应中读取文件和修改 Blender 数据。
|
单文件功能按业务命名;复杂功能包在 `operators.py` 定义 Operator、对应 WorkSpaceTool 和入口协调逻辑,其余模块承载具体实现。包的 `__init__.py` 汇总导出,类型在 `operators/__init__.py` 和扩展 `__init__.py` 汇总注册。AI Operator 使用普通字典提交任务,并在主线程响应中读取文件和修改 Blender 数据。
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Mask Alpha 编辑
|
# Mask Alpha 编辑
|
||||||
|
|
||||||
`operators/image_edit_tool/mask.py` 定义 `EditImageAlpha` 和 `MaskTool`,使用 `common/viewport.py` 的 `ImageGesture` 管理 Lasso、Brush 与 Polyline。
|
`operators/mask_tool.py` 定义 `EditImageAlpha` 和 `MaskTool`,使用 `common/viewport.py` 的 `ImageGesture` 管理 Lasso、Brush 与 Polyline。
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
flowchart TD
|
flowchart TD
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Rectify 透视校正
|
# Rectify 透视校正
|
||||||
|
|
||||||
`operators/image_edit_tool/rectify.py` 定义 `RectifyImagePerspective` 与 `RectifyTool`,将图片内的四角区域校正为矩形。
|
`operators/rectify_tool.py` 定义 `RectifyImagePerspective` 与 `RectifyTool`,将图片内的四角区域校正为矩形。
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
flowchart TD
|
flowchart TD
|
||||||
|
|||||||
@@ -5,11 +5,9 @@ from .operators.clipboard_image import CLASSES as CLIPBOARD_CLASSES
|
|||||||
from .menu import AnyImageImageMenu, draw_image_context_menu
|
from .menu import AnyImageImageMenu, draw_image_context_menu
|
||||||
from .operators import CLASSES as OPERATOR_CLASSES
|
from .operators import CLASSES as OPERATOR_CLASSES
|
||||||
from .operators.cutout_tool import CutoutTool
|
from .operators.cutout_tool import CutoutTool
|
||||||
from .operators.image_edit_tool import (
|
from .operators.frame_tool import FrameTool
|
||||||
FrameTool,
|
from .operators.mask_tool import MaskTool
|
||||||
MaskTool,
|
from .operators.rectify_tool import RectifyTool
|
||||||
RectifyTool,
|
|
||||||
)
|
|
||||||
from .panel import ServerPanel
|
from .panel import ServerPanel
|
||||||
from .preferences import AnyImagePreferences
|
from .preferences import AnyImagePreferences
|
||||||
from .properties import AnyImageSettings
|
from .properties import AnyImageSettings
|
||||||
|
|||||||
@@ -12,8 +12,6 @@ from .image import (
|
|||||||
from .node import load_node_group
|
from .node import load_node_group
|
||||||
|
|
||||||
|
|
||||||
DISPLACEMENT_STRENGTH = 1.0
|
|
||||||
DISPLACEMENT_MIDLEVEL = 0.0
|
|
||||||
IMAGE_MATERIAL_NODE_GROUP_NAME = "O Image Layer"
|
IMAGE_MATERIAL_NODE_GROUP_NAME = "O Image Layer"
|
||||||
DEPTH_MATERIAL_NODE_GROUP_NAME = "O Image Depth Layer"
|
DEPTH_MATERIAL_NODE_GROUP_NAME = "O Image Depth Layer"
|
||||||
SHADELESS_NODE_GROUP_NAME = "O Shadeless"
|
SHADELESS_NODE_GROUP_NAME = "O Shadeless"
|
||||||
|
|||||||
152
src/anyimage/licenses/scikit-image.txt
Normal file
152
src/anyimage/licenses/scikit-image.txt
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
Files: *
|
||||||
|
Copyright: 2009-2022 the scikit-image team
|
||||||
|
License: BSD-3-Clause
|
||||||
|
|
||||||
|
Files: doc/source/themes/scikit-image/layout.html
|
||||||
|
Copyright: 2007-2010 the Sphinx team
|
||||||
|
License: BSD-3-Clause
|
||||||
|
|
||||||
|
Files: skimage/feature/_canny.py
|
||||||
|
skimage/filters/edges.py
|
||||||
|
skimage/filters/_rank_order.py
|
||||||
|
skimage/morphology/_skeletonize.py
|
||||||
|
skimage/morphology/tests/test_watershed.py
|
||||||
|
skimage/morphology/watershed.py
|
||||||
|
skimage/segmentation/heap_general.pxi
|
||||||
|
skimage/segmentation/heap_watershed.pxi
|
||||||
|
skimage/segmentation/_watershed.py
|
||||||
|
skimage/segmentation/_watershed_cy.pyx
|
||||||
|
Copyright: 2003-2009 Massachusetts Institute of Technology
|
||||||
|
2009-2011 Broad Institute
|
||||||
|
2003 Lee Kamentsky
|
||||||
|
2003-2005 Peter J. Verveer
|
||||||
|
License: BSD-3-Clause
|
||||||
|
|
||||||
|
Files: skimage/filters/thresholding.py
|
||||||
|
skimage/graph/_mcp.pyx
|
||||||
|
skimage/graph/heap.pyx
|
||||||
|
Copyright: 2009-2015 Board of Regents of the University of
|
||||||
|
Wisconsin-Madison, Broad Institute of MIT and Harvard,
|
||||||
|
and Max Planck Institute of Molecular Cell Biology and
|
||||||
|
Genetics
|
||||||
|
2009 Zachary Pincus
|
||||||
|
2009 Almar Klein
|
||||||
|
License: BSD-2-Clause
|
||||||
|
|
||||||
|
File: skimage/morphology/grayreconstruct.py
|
||||||
|
skimage/morphology/tests/test_reconstruction.py
|
||||||
|
Copyright: 2003-2009 Massachusetts Institute of Technology
|
||||||
|
2009-2011 Broad Institute
|
||||||
|
2003 Lee Kamentsky
|
||||||
|
License: BSD-3-Clause
|
||||||
|
|
||||||
|
File: skimage/morphology/_grayreconstruct.pyx
|
||||||
|
Copyright: 2003-2009 Massachusetts Institute of Technology
|
||||||
|
2009-2011 Broad Institute
|
||||||
|
2003 Lee Kamentsky
|
||||||
|
2022 Gregory Lee (added a 64-bit integer variant for large images)
|
||||||
|
License: BSD-3-Clause
|
||||||
|
|
||||||
|
File: skimage/segmentation/_expand_labels.py
|
||||||
|
Copyright: 2020 Broad Institute
|
||||||
|
2020 CellProfiler team
|
||||||
|
License: BSD-3-Clause
|
||||||
|
|
||||||
|
File: skimage/exposure/_adapthist.py
|
||||||
|
Copyright: 1994 Karel Zuiderveld
|
||||||
|
License: BSD-3-Clause
|
||||||
|
|
||||||
|
Function: skimage/morphology/_skeletonize_various_cy.pyx:_skeletonize_loop
|
||||||
|
Copyright: 2003-2009 Massachusetts Institute of Technology
|
||||||
|
2009-2011 Broad Institute
|
||||||
|
2003 Lee Kamentsky
|
||||||
|
License: BSD-3-Clause
|
||||||
|
|
||||||
|
Function: skimage/_shared/version_requirements.py:_check_version
|
||||||
|
Copyright: 2013 The IPython Development Team
|
||||||
|
License: BSD-3-Clause
|
||||||
|
|
||||||
|
Function: skimage/_shared/version_requirements.py:is_installed
|
||||||
|
Copyright: 2009-2011 Pierre Raybaut
|
||||||
|
License: MIT
|
||||||
|
|
||||||
|
File: skimage/feature/_fisher_vector.py
|
||||||
|
Copyright: 2014 2014 Dan Oneata
|
||||||
|
License: MIT
|
||||||
|
|
||||||
|
File: skimage/_vendored/numpy_lookfor.py
|
||||||
|
Copyright: 2005-2023, NumPy Developers
|
||||||
|
License: BSD-3-Clause
|
||||||
|
|
||||||
|
File: skimage/transform/_thin_plate_splines.py
|
||||||
|
Copyright: 2007 Zachary Pincus
|
||||||
|
License: BSD-3-Clause
|
||||||
|
|
||||||
|
License: BSD-2-Clause
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
.
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE HOLDERS OR
|
||||||
|
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
License: BSD-3-Clause
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the University nor the names of its contributors
|
||||||
|
may be used to endorse or promote products derived from this software
|
||||||
|
without specific prior written permission.
|
||||||
|
.
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE HOLDERS OR
|
||||||
|
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
License: MIT
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@@ -3,7 +3,9 @@ from .cutout_tool import (
|
|||||||
CutoutSelectionToShape,
|
CutoutSelectionToShape,
|
||||||
SelectCutoutSelection,
|
SelectCutoutSelection,
|
||||||
)
|
)
|
||||||
from .image_edit_tool import CLASSES as IMAGE_EDIT_TOOL_CLASSES
|
from .frame_tool import FrameImages
|
||||||
|
from .mask_tool import EditImageAlpha
|
||||||
|
from .rectify_tool import RectifyImagePerspective
|
||||||
from .convert_to_plane import (
|
from .convert_to_plane import (
|
||||||
ConvertToDepthPlane,
|
ConvertToDepthPlane,
|
||||||
ConvertToPlane,
|
ConvertToPlane,
|
||||||
@@ -29,7 +31,9 @@ CLASSES = (
|
|||||||
SelectCutoutSelection,
|
SelectCutoutSelection,
|
||||||
RunBackgroundRemoval,
|
RunBackgroundRemoval,
|
||||||
ClearModels,
|
ClearModels,
|
||||||
*IMAGE_EDIT_TOOL_CLASSES,
|
FrameImages,
|
||||||
|
EditImageAlpha,
|
||||||
|
RectifyImagePerspective,
|
||||||
RemoveImageBackground,
|
RemoveImageBackground,
|
||||||
UpscaleImage,
|
UpscaleImage,
|
||||||
ConvertToPlane,
|
ConvertToPlane,
|
||||||
|
|||||||
@@ -1,209 +1,15 @@
|
|||||||
import sys
|
from .operators import (
|
||||||
|
CLASSES,
|
||||||
import bpy
|
PasteClipboardImage,
|
||||||
|
TrackNativeCopy,
|
||||||
from .actions import (
|
register_keymaps,
|
||||||
PasteTargetError,
|
unregister_keymaps,
|
||||||
acquire_packed_image,
|
|
||||||
paste_image,
|
|
||||||
paste_location,
|
|
||||||
target_for_context,
|
|
||||||
)
|
|
||||||
from .clipboard import (
|
|
||||||
ClipboardImageError,
|
|
||||||
ClipboardImageUnavailable,
|
|
||||||
clipboard_change_token,
|
|
||||||
clipboard_image_supported,
|
|
||||||
read_clipboard_image,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
__all__ = (
|
||||||
_keymap_items = []
|
"CLASSES",
|
||||||
_native_copy_token = None
|
"PasteClipboardImage",
|
||||||
|
"TrackNativeCopy",
|
||||||
|
"register_keymaps",
|
||||||
class TrackNativeCopy(bpy.types.Operator):
|
"unregister_keymaps",
|
||||||
bl_idname = "anyimage.track_native_copy"
|
)
|
||||||
bl_label = "Track Native Copy"
|
|
||||||
bl_description = "Preserve Blender's native copy and paste priority"
|
|
||||||
bl_options = {"INTERNAL"}
|
|
||||||
|
|
||||||
def execute(self, _context):
|
|
||||||
global _native_copy_token
|
|
||||||
|
|
||||||
_native_copy_token = clipboard_change_token()
|
|
||||||
return {"PASS_THROUGH"}
|
|
||||||
|
|
||||||
|
|
||||||
class PasteClipboardImage(bpy.types.Operator):
|
|
||||||
bl_idname = "anyimage.paste_clipboard_image"
|
|
||||||
bl_label = "Paste Clipboard Image"
|
|
||||||
bl_description = "Paste and pack the clipboard image for the current editor"
|
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
|
||||||
|
|
||||||
import_as: bpy.props.EnumProperty(
|
|
||||||
name="Import As",
|
|
||||||
description="Choose the 3D View representation for the image",
|
|
||||||
items=(
|
|
||||||
(
|
|
||||||
"PLANE",
|
|
||||||
"Plane",
|
|
||||||
"Create a mesh plane with an image material",
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"REFERENCE",
|
|
||||||
"Reference Image",
|
|
||||||
"Create an image Empty like dragging an image into Blender",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
default="REFERENCE",
|
|
||||||
)
|
|
||||||
shadeless: bpy.props.BoolProperty(
|
|
||||||
name="Shadeless",
|
|
||||||
description=(
|
|
||||||
"Use an Emission shader so the image is unaffected by scene lighting"
|
|
||||||
),
|
|
||||||
default=False,
|
|
||||||
)
|
|
||||||
paste_target: bpy.props.StringProperty(
|
|
||||||
options={"HIDDEN", "SKIP_SAVE"},
|
|
||||||
)
|
|
||||||
location: bpy.props.FloatVectorProperty(
|
|
||||||
size=3,
|
|
||||||
options={"HIDDEN", "SKIP_SAVE"},
|
|
||||||
)
|
|
||||||
location_set: bpy.props.BoolProperty(
|
|
||||||
default=False,
|
|
||||||
options={"HIDDEN", "SKIP_SAVE"},
|
|
||||||
)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def poll(cls, context):
|
|
||||||
if not clipboard_image_supported():
|
|
||||||
return False
|
|
||||||
return target_for_context(context) is not None
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
return self._paste(context)
|
|
||||||
|
|
||||||
def invoke(self, context, event):
|
|
||||||
self.paste_target = target_for_context(context) or ""
|
|
||||||
location = paste_location(context, event)
|
|
||||||
if location is not None:
|
|
||||||
values = tuple(location)
|
|
||||||
self.location = (*values, 0.0)[:3]
|
|
||||||
self.location_set = True
|
|
||||||
return self._paste(context, event)
|
|
||||||
|
|
||||||
def draw(self, _context):
|
|
||||||
if self.paste_target != "PLANE":
|
|
||||||
return
|
|
||||||
self.layout.prop(self, "import_as")
|
|
||||||
if self.import_as == "PLANE":
|
|
||||||
self.layout.prop(self, "shadeless")
|
|
||||||
|
|
||||||
def _paste(self, context, event=None):
|
|
||||||
if _should_defer_to_native_paste():
|
|
||||||
return {"PASS_THROUGH"}
|
|
||||||
|
|
||||||
if not self.paste_target:
|
|
||||||
self.paste_target = target_for_context(context) or ""
|
|
||||||
|
|
||||||
try:
|
|
||||||
image_data, suffix = read_clipboard_image()
|
|
||||||
except ClipboardImageUnavailable:
|
|
||||||
return {"PASS_THROUGH"}
|
|
||||||
except ClipboardImageError as error:
|
|
||||||
self.report({"ERROR"}, str(error))
|
|
||||||
return {"CANCELLED"}
|
|
||||||
|
|
||||||
image = None
|
|
||||||
image_reused = False
|
|
||||||
try:
|
|
||||||
image, image_reused = acquire_packed_image(image_data, suffix)
|
|
||||||
location = None
|
|
||||||
if self.location_set:
|
|
||||||
location = self.location
|
|
||||||
if self.paste_target == "NODE":
|
|
||||||
location = location[:2]
|
|
||||||
paste_image(
|
|
||||||
context,
|
|
||||||
image,
|
|
||||||
event,
|
|
||||||
location=location,
|
|
||||||
import_as=self.import_as,
|
|
||||||
shadeless=self.shadeless,
|
|
||||||
)
|
|
||||||
except (OSError, RuntimeError, PasteTargetError) as error:
|
|
||||||
if image is not None and not image_reused and image.users == 0:
|
|
||||||
bpy.data.images.remove(image)
|
|
||||||
self.report({"ERROR"}, f"Unable to paste clipboard image: {error}")
|
|
||||||
return {"CANCELLED"}
|
|
||||||
|
|
||||||
self.report({"INFO"}, f"Pasted and packed {image.name}")
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
|
|
||||||
CLASSES = (TrackNativeCopy, PasteClipboardImage)
|
|
||||||
|
|
||||||
|
|
||||||
def register_keymaps():
|
|
||||||
_register_keymaps()
|
|
||||||
|
|
||||||
|
|
||||||
def unregister_keymaps():
|
|
||||||
global _native_copy_token
|
|
||||||
_unregister_keymaps()
|
|
||||||
_native_copy_token = None
|
|
||||||
|
|
||||||
|
|
||||||
def _should_defer_to_native_paste():
|
|
||||||
if _native_copy_token is None:
|
|
||||||
return False
|
|
||||||
return clipboard_change_token() == _native_copy_token
|
|
||||||
|
|
||||||
|
|
||||||
def _register_keymaps():
|
|
||||||
if not clipboard_image_supported():
|
|
||||||
return
|
|
||||||
|
|
||||||
window_manager = getattr(bpy.context, "window_manager", None)
|
|
||||||
keyconfigs = getattr(window_manager, "keyconfigs", None)
|
|
||||||
addon_keyconfig = getattr(keyconfigs, "addon", None)
|
|
||||||
if addon_keyconfig is None:
|
|
||||||
return
|
|
||||||
|
|
||||||
keymap_definitions = (
|
|
||||||
("3D View", "VIEW_3D"),
|
|
||||||
("Node Editor", "NODE_EDITOR"),
|
|
||||||
)
|
|
||||||
for keymap_name, space_type in keymap_definitions:
|
|
||||||
keymap = addon_keyconfig.keymaps.new(
|
|
||||||
name=keymap_name,
|
|
||||||
space_type=space_type,
|
|
||||||
)
|
|
||||||
modifiers = (
|
|
||||||
{"oskey": True}
|
|
||||||
if sys.platform == "darwin"
|
|
||||||
else {"ctrl": True}
|
|
||||||
)
|
|
||||||
keymap_item = keymap.keymap_items.new(
|
|
||||||
PasteClipboardImage.bl_idname,
|
|
||||||
"V",
|
|
||||||
"PRESS",
|
|
||||||
**modifiers,
|
|
||||||
)
|
|
||||||
_keymap_items.append((keymap, keymap_item))
|
|
||||||
copy_keymap_item = keymap.keymap_items.new(
|
|
||||||
TrackNativeCopy.bl_idname,
|
|
||||||
"C",
|
|
||||||
"PRESS",
|
|
||||||
**modifiers,
|
|
||||||
)
|
|
||||||
_keymap_items.append((keymap, copy_keymap_item))
|
|
||||||
|
|
||||||
|
|
||||||
def _unregister_keymaps():
|
|
||||||
for keymap, keymap_item in _keymap_items:
|
|
||||||
keymap.keymap_items.remove(keymap_item)
|
|
||||||
_keymap_items.clear()
|
|
||||||
|
|||||||
201
src/anyimage/operators/clipboard_image/operators.py
Normal file
201
src/anyimage/operators/clipboard_image/operators.py
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
|
||||||
|
from .actions import (
|
||||||
|
PasteTargetError,
|
||||||
|
acquire_packed_image,
|
||||||
|
paste_image,
|
||||||
|
paste_location,
|
||||||
|
target_for_context,
|
||||||
|
)
|
||||||
|
from .clipboard import (
|
||||||
|
ClipboardImageError,
|
||||||
|
ClipboardImageUnavailable,
|
||||||
|
clipboard_change_token,
|
||||||
|
clipboard_image_supported,
|
||||||
|
read_clipboard_image,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_keymap_items = []
|
||||||
|
_native_copy_token = None
|
||||||
|
|
||||||
|
|
||||||
|
class TrackNativeCopy(bpy.types.Operator):
|
||||||
|
bl_idname = "anyimage.track_native_copy"
|
||||||
|
bl_label = "Track Native Copy"
|
||||||
|
bl_description = "Preserve Blender's native copy and paste priority"
|
||||||
|
bl_options = {"INTERNAL"}
|
||||||
|
|
||||||
|
def execute(self, _context):
|
||||||
|
global _native_copy_token
|
||||||
|
|
||||||
|
_native_copy_token = clipboard_change_token()
|
||||||
|
return {"PASS_THROUGH"}
|
||||||
|
|
||||||
|
|
||||||
|
class PasteClipboardImage(bpy.types.Operator):
|
||||||
|
bl_idname = "anyimage.paste_clipboard_image"
|
||||||
|
bl_label = "Paste Clipboard Image"
|
||||||
|
bl_description = "Paste and pack the clipboard image for the current editor"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
|
import_as: bpy.props.EnumProperty(
|
||||||
|
name="Import As",
|
||||||
|
description="Choose the 3D View representation for the image",
|
||||||
|
items=(
|
||||||
|
(
|
||||||
|
"PLANE",
|
||||||
|
"Plane",
|
||||||
|
"Create a mesh plane with an image material",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"REFERENCE",
|
||||||
|
"Reference Image",
|
||||||
|
"Create an image Empty like dragging an image into Blender",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
default="REFERENCE",
|
||||||
|
)
|
||||||
|
shadeless: bpy.props.BoolProperty(
|
||||||
|
name="Shadeless",
|
||||||
|
description=(
|
||||||
|
"Use an Emission shader so the image is unaffected by scene lighting"
|
||||||
|
),
|
||||||
|
default=False,
|
||||||
|
)
|
||||||
|
paste_target: bpy.props.StringProperty(
|
||||||
|
options={"HIDDEN", "SKIP_SAVE"},
|
||||||
|
)
|
||||||
|
location: bpy.props.FloatVectorProperty(
|
||||||
|
size=3,
|
||||||
|
options={"HIDDEN", "SKIP_SAVE"},
|
||||||
|
)
|
||||||
|
location_set: bpy.props.BoolProperty(
|
||||||
|
default=False,
|
||||||
|
options={"HIDDEN", "SKIP_SAVE"},
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
if not clipboard_image_supported():
|
||||||
|
return False
|
||||||
|
return target_for_context(context) is not None
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
return self._paste(context)
|
||||||
|
|
||||||
|
def invoke(self, context, event):
|
||||||
|
self.paste_target = target_for_context(context) or ""
|
||||||
|
location = paste_location(context, event)
|
||||||
|
if location is not None:
|
||||||
|
values = tuple(location)
|
||||||
|
self.location = (*values, 0.0)[:3]
|
||||||
|
self.location_set = True
|
||||||
|
return self._paste(context, event)
|
||||||
|
|
||||||
|
def draw(self, _context):
|
||||||
|
if self.paste_target != "PLANE":
|
||||||
|
return
|
||||||
|
self.layout.prop(self, "import_as")
|
||||||
|
if self.import_as == "PLANE":
|
||||||
|
self.layout.prop(self, "shadeless")
|
||||||
|
|
||||||
|
def _paste(self, context, event=None):
|
||||||
|
if _should_defer_to_native_paste():
|
||||||
|
return {"PASS_THROUGH"}
|
||||||
|
|
||||||
|
if not self.paste_target:
|
||||||
|
self.paste_target = target_for_context(context) or ""
|
||||||
|
|
||||||
|
try:
|
||||||
|
image_data, suffix = read_clipboard_image()
|
||||||
|
except ClipboardImageUnavailable:
|
||||||
|
return {"PASS_THROUGH"}
|
||||||
|
except ClipboardImageError as error:
|
||||||
|
self.report({"ERROR"}, str(error))
|
||||||
|
return {"CANCELLED"}
|
||||||
|
|
||||||
|
image = None
|
||||||
|
image_reused = False
|
||||||
|
try:
|
||||||
|
image, image_reused = acquire_packed_image(image_data, suffix)
|
||||||
|
location = None
|
||||||
|
if self.location_set:
|
||||||
|
location = self.location
|
||||||
|
if self.paste_target == "NODE":
|
||||||
|
location = location[:2]
|
||||||
|
paste_image(
|
||||||
|
context,
|
||||||
|
image,
|
||||||
|
event,
|
||||||
|
location=location,
|
||||||
|
import_as=self.import_as,
|
||||||
|
shadeless=self.shadeless,
|
||||||
|
)
|
||||||
|
except (OSError, RuntimeError, PasteTargetError) as error:
|
||||||
|
if image is not None and not image_reused and image.users == 0:
|
||||||
|
bpy.data.images.remove(image)
|
||||||
|
self.report({"ERROR"}, f"Unable to paste clipboard image: {error}")
|
||||||
|
return {"CANCELLED"}
|
||||||
|
|
||||||
|
self.report({"INFO"}, f"Pasted and packed {image.name}")
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
CLASSES = (TrackNativeCopy, PasteClipboardImage)
|
||||||
|
|
||||||
|
|
||||||
|
def unregister_keymaps():
|
||||||
|
global _native_copy_token
|
||||||
|
for keymap, keymap_item in _keymap_items:
|
||||||
|
keymap.keymap_items.remove(keymap_item)
|
||||||
|
_keymap_items.clear()
|
||||||
|
_native_copy_token = None
|
||||||
|
|
||||||
|
|
||||||
|
def _should_defer_to_native_paste():
|
||||||
|
if _native_copy_token is None:
|
||||||
|
return False
|
||||||
|
return clipboard_change_token() == _native_copy_token
|
||||||
|
|
||||||
|
|
||||||
|
def register_keymaps():
|
||||||
|
if not clipboard_image_supported():
|
||||||
|
return
|
||||||
|
|
||||||
|
window_manager = getattr(bpy.context, "window_manager", None)
|
||||||
|
keyconfigs = getattr(window_manager, "keyconfigs", None)
|
||||||
|
addon_keyconfig = getattr(keyconfigs, "addon", None)
|
||||||
|
if addon_keyconfig is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
keymap_definitions = (
|
||||||
|
("3D View", "VIEW_3D"),
|
||||||
|
("Node Editor", "NODE_EDITOR"),
|
||||||
|
)
|
||||||
|
for keymap_name, space_type in keymap_definitions:
|
||||||
|
keymap = addon_keyconfig.keymaps.new(
|
||||||
|
name=keymap_name,
|
||||||
|
space_type=space_type,
|
||||||
|
)
|
||||||
|
modifiers = (
|
||||||
|
{"oskey": True}
|
||||||
|
if sys.platform == "darwin"
|
||||||
|
else {"ctrl": True}
|
||||||
|
)
|
||||||
|
keymap_item = keymap.keymap_items.new(
|
||||||
|
PasteClipboardImage.bl_idname,
|
||||||
|
"V",
|
||||||
|
"PRESS",
|
||||||
|
**modifiers,
|
||||||
|
)
|
||||||
|
_keymap_items.append((keymap, keymap_item))
|
||||||
|
copy_keymap_item = keymap.keymap_items.new(
|
||||||
|
TrackNativeCopy.bl_idname,
|
||||||
|
"C",
|
||||||
|
"PRESS",
|
||||||
|
**modifiers,
|
||||||
|
)
|
||||||
|
_keymap_items.append((keymap, copy_keymap_item))
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
"""Rectangular Plane and Depth Plane conversion operators."""
|
"""Rectangular Plane and Depth Plane conversion operators."""
|
||||||
|
|
||||||
from .conversion import (
|
from .operators import (
|
||||||
ConvertToDepthPlane,
|
ConvertToDepthPlane,
|
||||||
ConvertToPlane,
|
ConvertToPlane,
|
||||||
GenerateDepthPlane,
|
GenerateDepthPlane,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from .main import CutoutSelectionToShape, CutoutTool, SelectCutoutSelection
|
from .operators import CutoutSelectionToShape, CutoutTool, SelectCutoutSelection
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
"CutoutSelectionToShape",
|
"CutoutSelectionToShape",
|
||||||
|
|||||||
@@ -874,9 +874,6 @@ def teddy_balloon_heights(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
DEFAULT_ALGORITHM = "POISSON"
|
|
||||||
|
|
||||||
|
|
||||||
def cotangent_poisson_field(
|
def cotangent_poisson_field(
|
||||||
planar_points,
|
planar_points,
|
||||||
planar_faces,
|
planar_faces,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import math
|
|||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
from ...common.image import (
|
from ..common.image import (
|
||||||
MAX_PROJECTIVE_OUTPUT_PIXELS,
|
MAX_PROJECTIVE_OUTPUT_PIXELS,
|
||||||
PROJECTIVE_CHUNK_ROWS,
|
PROJECTIVE_CHUNK_ROWS,
|
||||||
create_image_edit_result,
|
create_image_edit_result,
|
||||||
@@ -16,8 +16,8 @@ from ...common.image import (
|
|||||||
transform_homography,
|
transform_homography,
|
||||||
video_total_frames,
|
video_total_frames,
|
||||||
)
|
)
|
||||||
from ...preferences import configured_max_frame_resolution
|
from ..preferences import configured_max_frame_resolution
|
||||||
from ...common.viewport import (
|
from ..common.viewport import (
|
||||||
active_image_edit_source,
|
active_image_edit_source,
|
||||||
active_view3d_tool_id,
|
active_view3d_tool_id,
|
||||||
draw_dashed_line,
|
draw_dashed_line,
|
||||||
@@ -28,7 +28,7 @@ from ...common.viewport import (
|
|||||||
rectangle_screen_path,
|
rectangle_screen_path,
|
||||||
report_image_edit_exception,
|
report_image_edit_exception,
|
||||||
)
|
)
|
||||||
from ...common.selection import ImageEditWarning, clip_polygon_halfplanes
|
from ..common.selection import ImageEditWarning, clip_polygon_halfplanes
|
||||||
|
|
||||||
FRAME_TOOL_ID = "anyimage.frame"
|
FRAME_TOOL_ID = "anyimage.frame"
|
||||||
PROJECTIVE_RELATIVE_EPSILON = 1e-12
|
PROJECTIVE_RELATIVE_EPSILON = 1e-12
|
||||||
@@ -646,17 +646,3 @@ class FrameTool(bpy.types.WorkSpaceTool):
|
|||||||
bl_icon = "ops.sculpt.border_mask"
|
bl_icon = "ops.sculpt.border_mask"
|
||||||
bl_operator = FrameImages.bl_idname
|
bl_operator = FrameImages.bl_idname
|
||||||
bl_keymap = image_edit_drag_keymap(FrameImages.bl_idname)
|
bl_keymap = image_edit_drag_keymap(FrameImages.bl_idname)
|
||||||
|
|
||||||
|
|
||||||
class ActivateImageEditTool(bpy.types.Operator):
|
|
||||||
bl_idname = "anyimage.activate_image_edit_tool"
|
|
||||||
bl_label = "Image Edit"
|
|
||||||
bl_description = "Activate Frame in the 3D Viewport"
|
|
||||||
bl_options = {"INTERNAL"}
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def poll(cls, context):
|
|
||||||
return image_edit_poll(context)
|
|
||||||
|
|
||||||
def execute(self, _context):
|
|
||||||
return bpy.ops.wm.tool_set_by_id(name=FRAME_TOOL_ID, space_type="VIEW_3D")
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
from .frame import ActivateImageEditTool, FrameImages, FrameTool
|
|
||||||
from .mask import EditImageAlpha, MaskTool
|
|
||||||
from .rectify import RectifyImagePerspective, RectifyTool
|
|
||||||
|
|
||||||
|
|
||||||
CLASSES = (
|
|
||||||
FrameImages,
|
|
||||||
EditImageAlpha,
|
|
||||||
ActivateImageEditTool,
|
|
||||||
RectifyImagePerspective,
|
|
||||||
)
|
|
||||||
|
|
||||||
__all__ = (
|
|
||||||
"CLASSES",
|
|
||||||
"FrameTool",
|
|
||||||
"MaskTool",
|
|
||||||
"RectifyTool",
|
|
||||||
)
|
|
||||||
@@ -1,25 +1,25 @@
|
|||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
from ...common.image import (
|
from ..common.image import (
|
||||||
create_image_edit_result,
|
create_image_edit_result,
|
||||||
image_empty_bounds,
|
image_empty_bounds,
|
||||||
image_rgba,
|
image_rgba,
|
||||||
replace_empty_image,
|
replace_empty_image,
|
||||||
require_image_empty,
|
require_image_empty,
|
||||||
)
|
)
|
||||||
from ...common.selection import (
|
from ..common.selection import (
|
||||||
rasterize_selection_path,
|
rasterize_selection_path,
|
||||||
rasterize_selection_union,
|
rasterize_selection_union,
|
||||||
SelectionPath,
|
SelectionPath,
|
||||||
)
|
)
|
||||||
from ...common.viewport import (
|
from ..common.viewport import (
|
||||||
brush_footprint_polygons,
|
brush_footprint_polygons,
|
||||||
ImageGesture,
|
ImageGesture,
|
||||||
image_edit_point_keymap,
|
image_edit_point_keymap,
|
||||||
report_image_edit_exception,
|
report_image_edit_exception,
|
||||||
screen_path_to_image_pixels,
|
screen_path_to_image_pixels,
|
||||||
)
|
)
|
||||||
from ...properties import (
|
from ..properties import (
|
||||||
mask_gesture_property,
|
mask_gesture_property,
|
||||||
mask_mode_property,
|
mask_mode_property,
|
||||||
mask_radius_property,
|
mask_radius_property,
|
||||||
@@ -3,7 +3,7 @@ import math
|
|||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
from ...common.viewport import (
|
from ..common.viewport import (
|
||||||
active_view3d_tool_id,
|
active_view3d_tool_id,
|
||||||
deserialize_matrix,
|
deserialize_matrix,
|
||||||
draw_dashed_line,
|
draw_dashed_line,
|
||||||
@@ -16,8 +16,8 @@ from ...common.viewport import (
|
|||||||
screen_path_to_image_pixels,
|
screen_path_to_image_pixels,
|
||||||
serialize_matrix,
|
serialize_matrix,
|
||||||
)
|
)
|
||||||
from ...common.selection import clip_polygon_halfplanes, trim_pixels_to_alpha
|
from ..common.selection import clip_polygon_halfplanes, trim_pixels_to_alpha
|
||||||
from ...common.image import (
|
from ..common.image import (
|
||||||
create_image_edit_result,
|
create_image_edit_result,
|
||||||
image_base_name,
|
image_base_name,
|
||||||
image_pixels,
|
image_pixels,
|
||||||
@@ -9,8 +9,6 @@ from .server import model_catalog as shared_model_catalog
|
|||||||
|
|
||||||
BEN2_MODEL_KEY = "BEN2_BASE"
|
BEN2_MODEL_KEY = "BEN2_BASE"
|
||||||
REALESRGAN_GENERAL_WDN_MODEL_KEY = shared_model_catalog.DEFAULT_UPSCALE_MODEL_KEY
|
REALESRGAN_GENERAL_WDN_MODEL_KEY = shared_model_catalog.DEFAULT_UPSCALE_MODEL_KEY
|
||||||
SAFMN_MODEL_KEY = shared_model_catalog.SAFMN_MODEL.key
|
|
||||||
REALESRGAN_X4PLUS_MODEL_KEY = shared_model_catalog.REALESRGAN_X4PLUS.key
|
|
||||||
DEFAULT_MOGE2_MODEL_KEY = "MOGE2_VITS_NORMAL"
|
DEFAULT_MOGE2_MODEL_KEY = "MOGE2_VITS_NORMAL"
|
||||||
REQUIRED_MODEL_KEYS = (
|
REQUIRED_MODEL_KEYS = (
|
||||||
DEFAULT_MOGE2_MODEL_KEY,
|
DEFAULT_MOGE2_MODEL_KEY,
|
||||||
@@ -85,10 +83,6 @@ def model_ready(model_key):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def required_models_ready():
|
|
||||||
return not ai_status()["missing_models"]
|
|
||||||
|
|
||||||
|
|
||||||
def ai_status():
|
def ai_status():
|
||||||
environment_ready = runtime.environment_ready()
|
environment_ready = runtime.environment_ready()
|
||||||
ready_models = {model["key"] for model in model_catalog() if model.get("ready")}
|
ready_models = {model["key"] for model in model_catalog() if model.get("ready")}
|
||||||
|
|||||||
@@ -1,7 +1 @@
|
|||||||
from .projection import unproject_camera_depth, unproject_depth_frame
|
"""Depth and normal artifact processing."""
|
||||||
|
|
||||||
|
|
||||||
__all__ = (
|
|
||||||
"unproject_camera_depth",
|
|
||||||
"unproject_depth_frame",
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
def unproject_depth_frame(depth, intrinsics, extrinsics):
|
|
||||||
import numpy as np
|
|
||||||
|
|
||||||
height, width = depth.shape
|
|
||||||
x, y = np.meshgrid(
|
|
||||||
np.arange(width, dtype=np.float32),
|
|
||||||
np.arange(height, dtype=np.float32),
|
|
||||||
)
|
|
||||||
pixels = np.stack((x, y, np.ones_like(x)), axis=-1).reshape(-1, 3)
|
|
||||||
rays = (np.linalg.inv(intrinsics) @ pixels.T).T
|
|
||||||
camera_points = rays * depth.reshape(-1, 1)
|
|
||||||
camera_points = np.column_stack(
|
|
||||||
(camera_points, np.ones(camera_points.shape[0], dtype=np.float32))
|
|
||||||
)
|
|
||||||
world_to_camera = np.eye(4, dtype=np.float32)
|
|
||||||
world_to_camera[: extrinsics.shape[0], :4] = extrinsics
|
|
||||||
world_points = (np.linalg.inv(world_to_camera) @ camera_points.T).T
|
|
||||||
return world_points[:, :3].reshape(height, width, 3)
|
|
||||||
|
|
||||||
|
|
||||||
def unproject_camera_depth(depth, intrinsics):
|
|
||||||
import numpy as np
|
|
||||||
|
|
||||||
height, width = depth.shape
|
|
||||||
x, y = np.meshgrid(
|
|
||||||
np.arange(width, dtype=np.float32),
|
|
||||||
np.arange(height, dtype=np.float32),
|
|
||||||
)
|
|
||||||
pixels = np.stack((x, y, np.ones_like(x)), axis=-1).reshape(-1, 3)
|
|
||||||
rays = (np.linalg.inv(intrinsics) @ pixels.T).T
|
|
||||||
return (rays * depth.reshape(-1, 1)).reshape(height, width, 3)
|
|
||||||
@@ -178,7 +178,6 @@ MOGE2_MODELS = {
|
|||||||
),),
|
),),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
MOGE2_MODEL = MOGE2_MODELS["MOGE2_VITS_NORMAL"]
|
|
||||||
DOWNLOADABLE_MODELS = {
|
DOWNLOADABLE_MODELS = {
|
||||||
BEN2_MODEL.key: BEN2_MODEL,
|
BEN2_MODEL.key: BEN2_MODEL,
|
||||||
**UPSCALE_MODELS,
|
**UPSCALE_MODELS,
|
||||||
@@ -193,11 +192,6 @@ def get_downloadable_model(model_key):
|
|||||||
raise ValueError(f"Unknown model: {model_key}") from error
|
raise ValueError(f"Unknown model: {model_key}") from error
|
||||||
|
|
||||||
|
|
||||||
def model_directory_name(model_key):
|
|
||||||
"""Return the model's folder name inside the shared models directory."""
|
|
||||||
return get_downloadable_model(model_key).directory_name
|
|
||||||
|
|
||||||
|
|
||||||
def model_record(model, ready=False):
|
def model_record(model, ready=False):
|
||||||
"""Return public model metadata exposed by the Models Resource."""
|
"""Return public model metadata exposed by the Models Resource."""
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ from pathlib import Path
|
|||||||
|
|
||||||
from .onnx_runtime import create_session as create_runtime_session
|
from .onnx_runtime import create_session as create_runtime_session
|
||||||
from .onnx_runtime import run_session
|
from .onnx_runtime import run_session
|
||||||
from .onnx_runtime import select_providers as select_providers
|
|
||||||
|
|
||||||
|
|
||||||
ONNX_FILENAME = "model.onnx"
|
ONNX_FILENAME = "model.onnx"
|
||||||
@@ -15,10 +14,6 @@ COREML_PROVIDER_OPTIONS = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def is_onnx_model(model_directory):
|
|
||||||
return (Path(model_directory) / ONNX_FILENAME).is_file()
|
|
||||||
|
|
||||||
|
|
||||||
def create_session(model_directory, requested_device="auto"):
|
def create_session(model_directory, requested_device="auto"):
|
||||||
path = Path(model_directory) / ONNX_FILENAME
|
path = Path(model_directory) / ONNX_FILENAME
|
||||||
return create_runtime_session(
|
return create_runtime_session(
|
||||||
|
|||||||
@@ -95,15 +95,3 @@ def run_session(
|
|||||||
"gpu:0",
|
"gpu:0",
|
||||||
)
|
)
|
||||||
return session.run(output_names, input_feed, run_options=run_options)
|
return session.run(output_names, input_feed, run_options=run_options)
|
||||||
|
|
||||||
|
|
||||||
def provider_label(session):
|
|
||||||
provider = session.get_providers()[0]
|
|
||||||
labels = {
|
|
||||||
"CUDAExecutionProvider": "CUDA",
|
|
||||||
"CoreMLExecutionProvider": "CoreML",
|
|
||||||
"DmlExecutionProvider": "DirectML",
|
|
||||||
"OpenVINOExecutionProvider": "OpenVINO",
|
|
||||||
"CPUExecutionProvider": "CPU",
|
|
||||||
}
|
|
||||||
return labels.get(provider, provider)
|
|
||||||
|
|||||||
@@ -114,13 +114,13 @@ class BlenderTestCase(unittest.TestCase):
|
|||||||
cls.ai = importlib.import_module("anyimage.common.ai")
|
cls.ai = importlib.import_module("anyimage.common.ai")
|
||||||
cls.image_data = importlib.import_module("anyimage.common.image")
|
cls.image_data = importlib.import_module("anyimage.common.image")
|
||||||
cls.convert_to_plane = importlib.import_module(
|
cls.convert_to_plane = importlib.import_module(
|
||||||
"anyimage.operators.convert_to_plane.conversion"
|
"anyimage.operators.convert_to_plane.operators"
|
||||||
)
|
)
|
||||||
cls.convert_to_plane_object = importlib.import_module(
|
cls.convert_to_plane_object = importlib.import_module(
|
||||||
"anyimage.operators.convert_to_plane.object"
|
"anyimage.operators.convert_to_plane.object"
|
||||||
)
|
)
|
||||||
cls.cutout_main = importlib.import_module(
|
cls.cutout_main = importlib.import_module(
|
||||||
"anyimage.operators.cutout_tool.main"
|
"anyimage.operators.cutout_tool.operators"
|
||||||
)
|
)
|
||||||
cls.remove_background = importlib.import_module(
|
cls.remove_background = importlib.import_module(
|
||||||
"anyimage.operators.remove_background"
|
"anyimage.operators.remove_background"
|
||||||
@@ -128,14 +128,14 @@ class BlenderTestCase(unittest.TestCase):
|
|||||||
cls.upscale = importlib.import_module("anyimage.operators.upscale")
|
cls.upscale = importlib.import_module("anyimage.operators.upscale")
|
||||||
cls.image_interaction = importlib.import_module("anyimage.common.viewport")
|
cls.image_interaction = importlib.import_module("anyimage.common.viewport")
|
||||||
cls.edit_mask = importlib.import_module(
|
cls.edit_mask = importlib.import_module(
|
||||||
"anyimage.operators.image_edit_tool.mask"
|
"anyimage.operators.mask_tool"
|
||||||
)
|
)
|
||||||
cls.image_selection = importlib.import_module("anyimage.common.selection")
|
cls.image_selection = importlib.import_module("anyimage.common.selection")
|
||||||
cls.image_frame = importlib.import_module(
|
cls.image_frame = importlib.import_module(
|
||||||
"anyimage.operators.image_edit_tool.frame"
|
"anyimage.operators.frame_tool"
|
||||||
)
|
)
|
||||||
cls.rectify = importlib.import_module(
|
cls.rectify = importlib.import_module(
|
||||||
"anyimage.operators.image_edit_tool.rectify"
|
"anyimage.operators.rectify_tool"
|
||||||
)
|
)
|
||||||
cls.cutout_geometry = importlib.import_module(
|
cls.cutout_geometry = importlib.import_module(
|
||||||
"anyimage.operators.cutout_tool.geometry"
|
"anyimage.operators.cutout_tool.geometry"
|
||||||
|
|||||||
@@ -65,10 +65,6 @@ class AddonRegistrationTest(BlenderTestCase):
|
|||||||
frame_operator = self.image_frame.FrameImages
|
frame_operator = self.image_frame.FrameImages
|
||||||
self.assertIn(operator, self.anyimage.CLASSES)
|
self.assertIn(operator, self.anyimage.CLASSES)
|
||||||
self.assertIn(frame_operator, self.anyimage.CLASSES)
|
self.assertIn(frame_operator, self.anyimage.CLASSES)
|
||||||
self.assertIn(
|
|
||||||
self.image_frame.ActivateImageEditTool,
|
|
||||||
self.anyimage.CLASSES,
|
|
||||||
)
|
|
||||||
self.assertIn(
|
self.assertIn(
|
||||||
self.rectify.RectifyImagePerspective,
|
self.rectify.RectifyImagePerspective,
|
||||||
self.anyimage.CLASSES,
|
self.anyimage.CLASSES,
|
||||||
|
|||||||
@@ -206,4 +206,4 @@ class AiSetupTest(BlenderTestCase):
|
|||||||
side_effect=AssertionError("UI must not start the Server"),
|
side_effect=AssertionError("UI must not start the Server"),
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
self.assertTrue(properties.required_models_ready())
|
self.assertEqual(properties.ai_status()["missing_models"], ())
|
||||||
|
|||||||
@@ -191,8 +191,8 @@ def test_isolated_decode_failure_releases_copy():
|
|||||||
|
|
||||||
def test_mask_pack_reopen_add_and_repeat_frame_preserve_hidden_color(tmp_path):
|
def test_mask_pack_reopen_add_and_repeat_frame_preserve_hidden_color(tmp_path):
|
||||||
from anyimage.common.selection import SelectionMask
|
from anyimage.common.selection import SelectionMask
|
||||||
from anyimage.operators.image_edit_tool.mask import apply_alpha_mask
|
from anyimage.operators.mask_tool import apply_alpha_mask
|
||||||
from anyimage.operators.image_edit_tool import frame
|
from anyimage.operators import frame_tool as frame
|
||||||
|
|
||||||
source = bpy.data.images.new("Roundtrip source", width=2, height=2, alpha=True)
|
source = bpy.data.images.new("Roundtrip source", width=2, height=2, alpha=True)
|
||||||
rgba = np.tile(np.array([0.2, 0.4, 0.8, 1], dtype=np.float32), (2, 2, 1))
|
rgba = np.tile(np.array([0.2, 0.4, 0.8, 1], dtype=np.float32), (2, 2, 1))
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import pytest
|
|||||||
sys.path.insert(0, str(Path(__file__).parents[1] / "src"))
|
sys.path.insert(0, str(Path(__file__).parents[1] / "src"))
|
||||||
|
|
||||||
from anyimage.common import selection, viewport
|
from anyimage.common import selection, viewport
|
||||||
from anyimage.operators.image_edit_tool import mask
|
from anyimage.operators import mask_tool as mask
|
||||||
|
|
||||||
|
|
||||||
def test_simplified_segments_bound_every_original_sample():
|
def test_simplified_segments_bound_every_original_sample():
|
||||||
|
|||||||
@@ -64,10 +64,10 @@ class ClipboardImageTest(unittest.TestCase):
|
|||||||
operators.__path__ = [str(PROJECT_ROOT / "src" / "anyimage" / "operators")]
|
operators.__path__ = [str(PROJECT_ROOT / "src" / "anyimage" / "operators")]
|
||||||
sys.modules["anyimage.operators"] = operators
|
sys.modules["anyimage.operators"] = operators
|
||||||
cls.addon.clipboard_image = importlib.import_module(
|
cls.addon.clipboard_image = importlib.import_module(
|
||||||
"anyimage.operators.clipboard_image"
|
"anyimage.operators.clipboard_image.operators"
|
||||||
)
|
)
|
||||||
cls.actions = cls.addon.clipboard_image.actions
|
cls.actions = importlib.import_module("anyimage.operators.clipboard_image.actions")
|
||||||
cls.clipboard = cls.addon.clipboard_image.clipboard
|
cls.clipboard = importlib.import_module("anyimage.operators.clipboard_image.clipboard")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def tearDownClass(cls):
|
def tearDownClass(cls):
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ sys.path.insert(0, str(SOURCE_ROOT))
|
|||||||
from anyimage.common.selection import SelectionPath
|
from anyimage.common.selection import SelectionPath
|
||||||
from anyimage.common import viewport
|
from anyimage.common import viewport
|
||||||
from anyimage.operators.cutout_tool import interaction
|
from anyimage.operators.cutout_tool import interaction
|
||||||
from anyimage.operators.cutout_tool import main as cutout_main
|
from anyimage.operators.cutout_tool import operators as cutout_main
|
||||||
|
|
||||||
|
|
||||||
class Pie:
|
class Pie:
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ from anyimage.common import material as material_data
|
|||||||
from anyimage.common import object as object_data
|
from anyimage.common import object as object_data
|
||||||
from anyimage.common.selection import ImageEditWarning, SelectionPath, rasterize_selection_path
|
from anyimage.common.selection import ImageEditWarning, SelectionPath, rasterize_selection_path
|
||||||
from anyimage.operators.cutout_tool import geometry as cutout_geometry
|
from anyimage.operators.cutout_tool import geometry as cutout_geometry
|
||||||
from anyimage.operators.cutout_tool import main as cutout_main
|
from anyimage.operators.cutout_tool import operators as cutout_main
|
||||||
from anyimage.operators.cutout_tool import object as cutout_object
|
from anyimage.operators.cutout_tool import object as cutout_object
|
||||||
from anyimage.operators.cutout_tool import shape as cutout_shape
|
from anyimage.operators.cutout_tool import shape as cutout_shape
|
||||||
from anyimage.server.geometry.depth_texture import (
|
from anyimage.server.geometry.depth_texture import (
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ from cutout import build_cutout_group
|
|||||||
from cutout_volume import build_volume_fields
|
from cutout_volume import build_volume_fields
|
||||||
from cutout_rounding import build_volume_rounding
|
from cutout_rounding import build_volume_rounding
|
||||||
from anyimage.operators.cutout_tool.object import load_cutout_node_group
|
from anyimage.operators.cutout_tool.object import load_cutout_node_group
|
||||||
from anyimage.operators.cutout_tool.main import normal_mode_for_shape
|
from anyimage.operators.cutout_tool.operators import normal_mode_for_shape
|
||||||
from anyimage.operators.cutout_tool.geometry import refine_balloon_triangles, poisson_balloon_profile
|
from anyimage.operators.cutout_tool.geometry import refine_balloon_triangles, poisson_balloon_profile
|
||||||
from anyimage.common.object import modifier_input_identifier, set_modifier_input
|
from anyimage.common.object import modifier_input_identifier, set_modifier_input
|
||||||
|
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ class ExtensionPackagingTest(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertIn("__init__.py", names)
|
self.assertIn("__init__.py", names)
|
||||||
self.assertIn("operators/clipboard_image/__init__.py", names)
|
self.assertIn("operators/clipboard_image/__init__.py", names)
|
||||||
|
self.assertIn("operators/clipboard_image/operators.py", names)
|
||||||
self.assertIn("operators/clipboard_image/actions.py", names)
|
self.assertIn("operators/clipboard_image/actions.py", names)
|
||||||
self.assertIn("operators/clipboard_image/clipboard.py", names)
|
self.assertIn("operators/clipboard_image/clipboard.py", names)
|
||||||
self.assertIn("blender_manifest.toml", names)
|
self.assertIn("blender_manifest.toml", names)
|
||||||
@@ -91,7 +92,7 @@ class ExtensionPackagingTest(unittest.TestCase):
|
|||||||
"common/selection.py",
|
"common/selection.py",
|
||||||
"common/viewport.py",
|
"common/viewport.py",
|
||||||
"operators/cutout_tool/__init__.py",
|
"operators/cutout_tool/__init__.py",
|
||||||
"operators/cutout_tool/main.py",
|
"operators/cutout_tool/operators.py",
|
||||||
"operators/cutout_tool/interaction.py",
|
"operators/cutout_tool/interaction.py",
|
||||||
"operators/cutout_tool/geometry.py",
|
"operators/cutout_tool/geometry.py",
|
||||||
"operators/cutout_tool/fine_mesh.py",
|
"operators/cutout_tool/fine_mesh.py",
|
||||||
@@ -99,12 +100,11 @@ class ExtensionPackagingTest(unittest.TestCase):
|
|||||||
"operators/cutout_tool/shape.py",
|
"operators/cutout_tool/shape.py",
|
||||||
"operators/convert_to_plane/__init__.py",
|
"operators/convert_to_plane/__init__.py",
|
||||||
"operators/convert_to_plane/object.py",
|
"operators/convert_to_plane/object.py",
|
||||||
"operators/convert_to_plane/conversion.py",
|
"operators/convert_to_plane/operators.py",
|
||||||
"operators/convert_to_plane/image_plane.py",
|
"operators/convert_to_plane/image_plane.py",
|
||||||
"operators/image_edit_tool/__init__.py",
|
"operators/frame_tool.py",
|
||||||
"operators/image_edit_tool/frame.py",
|
"operators/mask_tool.py",
|
||||||
"operators/image_edit_tool/mask.py",
|
"operators/rectify_tool.py",
|
||||||
"operators/image_edit_tool/rectify.py",
|
|
||||||
"operators/ai_setup.py",
|
"operators/ai_setup.py",
|
||||||
"operators/remove_background.py",
|
"operators/remove_background.py",
|
||||||
):
|
):
|
||||||
@@ -121,7 +121,6 @@ class ExtensionPackagingTest(unittest.TestCase):
|
|||||||
)
|
)
|
||||||
self.assertIn("server/media/input.py", names)
|
self.assertIn("server/media/input.py", names)
|
||||||
self.assertIn("common/depth.py", names)
|
self.assertIn("common/depth.py", names)
|
||||||
self.assertIn("server/geometry/projection.py", names)
|
|
||||||
self.assertIn("server/models/geometry.py", names)
|
self.assertIn("server/models/geometry.py", names)
|
||||||
self.assertIn("server/jobs/remove_background.py", names)
|
self.assertIn("server/jobs/remove_background.py", names)
|
||||||
self.assertIn("server/jobs/cutout.py", names)
|
self.assertIn("server/jobs/cutout.py", names)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import pytest
|
|||||||
sys.path.insert(0, str(Path(__file__).parents[1] / "src"))
|
sys.path.insert(0, str(Path(__file__).parents[1] / "src"))
|
||||||
|
|
||||||
from anyimage.common.image import premultiplied_rgba
|
from anyimage.common.image import premultiplied_rgba
|
||||||
from anyimage.operators.image_edit_tool import frame
|
from anyimage.operators import frame_tool as frame
|
||||||
|
|
||||||
|
|
||||||
def source(rgba, *, bounds=(-1, 1, -1, 1), depth=1, slope=0, active=True):
|
def source(rgba, *, bounds=(-1, 1, -1, 1), depth=1, slope=0, active=True):
|
||||||
@@ -39,7 +39,7 @@ def test_white_half_coverage_does_not_mix_canvas_black():
|
|||||||
|
|
||||||
def test_uncovered_canvas_has_no_rgb_to_reveal_with_mask_add():
|
def test_uncovered_canvas_has_no_rgb_to_reveal_with_mask_add():
|
||||||
from anyimage.common.selection import SelectionMask
|
from anyimage.common.selection import SelectionMask
|
||||||
from anyimage.operators.image_edit_tool.mask import apply_alpha_mask
|
from anyimage.operators.mask_tool import apply_alpha_mask
|
||||||
|
|
||||||
result = render((source([[[1, 1, 1, 1]]], bounds=(-0.5, 0.5, -0.5, 0.5)),), (8, 8))
|
result = render((source([[[1, 1, 1, 1]]], bounds=(-0.5, 0.5, -0.5, 0.5)),), (8, 8))
|
||||||
uncovered = result[..., 3] == 0
|
uncovered = result[..., 3] == 0
|
||||||
@@ -113,7 +113,7 @@ def test_packed_frame_mask_add_keeps_boundary_color(background):
|
|||||||
from PIL import Image
|
from PIL import Image
|
||||||
from anyimage.common.image import create_image_edit_result, image_rgba
|
from anyimage.common.image import create_image_edit_result, image_rgba
|
||||||
from anyimage.common.selection import SelectionMask
|
from anyimage.common.selection import SelectionMask
|
||||||
from anyimage.operators.image_edit_tool.mask import apply_alpha_mask
|
from anyimage.operators.mask_tool import apply_alpha_mask
|
||||||
|
|
||||||
bottom = source([[[background, background, background, 0]]], depth=2, active=False)
|
bottom = source([[[background, background, background, 0]]], depth=2, active=False)
|
||||||
top = source([[[1, 0, 0, 1]]], bounds=(-1, 0, -1, 1))
|
top = source([[[1, 0, 0, 1]]], bounds=(-1, 0, -1, 1))
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import pytest
|
|||||||
sys.path.insert(0, str(Path(__file__).parents[1] / "src"))
|
sys.path.insert(0, str(Path(__file__).parents[1] / "src"))
|
||||||
|
|
||||||
from anyimage.common.selection import clip_polygon_halfplanes
|
from anyimage.common.selection import clip_polygon_halfplanes
|
||||||
from anyimage.operators.image_edit_tool import frame
|
from anyimage.operators import frame_tool as frame
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("focal", [1, 1.7, 2, 4])
|
@pytest.mark.parametrize("focal", [1, 1.7, 2, 4])
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ sys.path.insert(0, str(SOURCE_ROOT))
|
|||||||
|
|
||||||
from anyimage.common import image as image_data
|
from anyimage.common import image as image_data
|
||||||
from anyimage.common.selection import SelectionMask
|
from anyimage.common.selection import SelectionMask
|
||||||
from anyimage.operators.image_edit_tool import mask as edit_mask
|
from anyimage.operators import mask_tool as edit_mask
|
||||||
from anyimage.operators.image_edit_tool import frame as edit_frame
|
from anyimage.operators import frame_tool as edit_frame
|
||||||
|
|
||||||
|
|
||||||
def test_image_edit_result_uses_complete_shared_source_name():
|
def test_image_edit_result_uses_complete_shared_source_name():
|
||||||
|
|||||||
@@ -93,27 +93,6 @@ class ImageMenuTest(BlenderTestCase):
|
|||||||
self.assertNotIn(("anyimage.setup_ai_environment", True), calls)
|
self.assertNotIn(("anyimage.setup_ai_environment", True), calls)
|
||||||
|
|
||||||
|
|
||||||
def test_image_edit_activation_defaults_to_frame(self):
|
|
||||||
calls = []
|
|
||||||
previous_ops = getattr(self.fake_bpy, "ops", None)
|
|
||||||
self.fake_bpy.ops = SimpleNamespace(
|
|
||||||
wm=SimpleNamespace(
|
|
||||||
tool_set_by_id=lambda **options: calls.append(options) or {"FINISHED"}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
try:
|
|
||||||
result = self.image_frame.ActivateImageEditTool().execute(None)
|
|
||||||
finally:
|
|
||||||
if previous_ops is None:
|
|
||||||
del self.fake_bpy.ops
|
|
||||||
else:
|
|
||||||
self.fake_bpy.ops = previous_ops
|
|
||||||
|
|
||||||
self.assertEqual(result, {"FINISHED"})
|
|
||||||
self.assertEqual(
|
|
||||||
calls,
|
|
||||||
[{"name": "anyimage.frame", "space_type": "VIEW_3D"}],
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_image_operators_stay_clickable_until_server_is_busy(self):
|
def test_image_operators_stay_clickable_until_server_is_busy(self):
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import pytest
|
|||||||
sys.path.insert(0, str(Path(__file__).parents[1] / "src"))
|
sys.path.insert(0, str(Path(__file__).parents[1] / "src"))
|
||||||
|
|
||||||
from anyimage.common import image, viewport
|
from anyimage.common import image, viewport
|
||||||
from anyimage.operators.image_edit_tool import mask
|
from anyimage.operators import mask_tool as mask
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("gesture", ["LASSO", "BRUSH", "POLYLINE"])
|
@pytest.mark.parametrize("gesture", ["LASSO", "BRUSH", "POLYLINE"])
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ class ModelCatalogTest(unittest.TestCase):
|
|||||||
|
|
||||||
def test_ben2_model_directory_uses_repository_name(self):
|
def test_ben2_model_directory_uses_repository_name(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.models.model_directory_name("BEN2_BASE"),
|
self.models.get_downloadable_model("BEN2_BASE").directory_name,
|
||||||
"BEN2-ONNX",
|
"BEN2-ONNX",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -67,16 +67,6 @@ class Moge2OnnxTest(unittest.TestCase):
|
|||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
cls.moge = load_module()
|
cls.moge = load_module()
|
||||||
|
|
||||||
def test_auto_provider_prefers_accelerated_runtime(self):
|
|
||||||
providers = self.moge.select_providers(
|
|
||||||
"auto",
|
|
||||||
["CPUExecutionProvider", "DmlExecutionProvider"],
|
|
||||||
)
|
|
||||||
|
|
||||||
self.assertEqual(
|
|
||||||
providers,
|
|
||||||
["DmlExecutionProvider", "CPUExecutionProvider"],
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_coreml_session_requires_static_input_partitions(self):
|
def test_coreml_session_requires_static_input_partitions(self):
|
||||||
calls = []
|
calls = []
|
||||||
@@ -107,13 +97,6 @@ class Moge2OnnxTest(unittest.TestCase):
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_explicit_unavailable_provider_falls_back_to_cpu(self):
|
|
||||||
providers = self.moge.select_providers(
|
|
||||||
"cuda",
|
|
||||||
["CPUExecutionProvider"],
|
|
||||||
)
|
|
||||||
|
|
||||||
self.assertEqual(providers, ["CPUExecutionProvider"])
|
|
||||||
|
|
||||||
def test_infer_uses_dynamic_token_input_and_numpy_postprocess(self):
|
def test_infer_uses_dynamic_token_input_and_numpy_postprocess(self):
|
||||||
height, width = 8, 12
|
height, width = 8, 12
|
||||||
|
|||||||
@@ -190,5 +190,27 @@ class OnnxRuntimeTest(unittest.TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_auto_provider_prefers_accelerated_runtime(self):
|
||||||
|
providers = onnx_runtime.select_providers(
|
||||||
|
"auto",
|
||||||
|
["CPUExecutionProvider", "DmlExecutionProvider"],
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
providers,
|
||||||
|
["DmlExecutionProvider", "CPUExecutionProvider"],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_explicit_unavailable_provider_falls_back_to_cpu(self):
|
||||||
|
providers = onnx_runtime.select_providers(
|
||||||
|
"cuda",
|
||||||
|
["CPUExecutionProvider"],
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(providers, ["CPUExecutionProvider"])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
Reference in New Issue
Block a user