预设的初始裁剪尺寸请修改这句:
makeRectangle(0, 0, 440, 440);
增加匹配的后缀名修改这句:
if (endsWith(list[i], ".jpg") || endsWith(list[i], ".png") || endsWith(list[i], ".tif") || endsWith(list[i], ".bmp")) {
预设的初始裁剪尺寸请修改这句:
makeRectangle(0, 0, 440, 440);
增加匹配的后缀名修改这句:
if (endsWith(list[i], ".jpg") || endsWith(list[i], ".png") || endsWith(list[i], ".tif") || endsWith(list[i], ".bmp")) {
imagej很强,但是ai不太擅长写这个脚本。边查api边用ai改了一晚上还是有致命的问题:
image的脚本不能添加按钮(至少是ijm脚本不行),而 waitForUser(“wait for human”)产生的ok channel效果,仅仅是继续下一行代码和结束脚本(脚本无法直接获取到底点击了哪个按钮来参与复杂逻辑 当然可以再加复选框,用复选框+按钮来充当自定义按钮,但是这难道不是很奇怪嘛,而且一晚上已经过去了,得明天再试了)。这就导致一个图片裁切后必须保存,不可以有复杂逻辑。一旦点击取消,就完全没有下一个图片的事情了。
缺少了缩放的处理逻辑。同上,因为没有复杂逻辑的原因,也不能预览到缩放结果并做相应对策。
// 默认裁剪参数
defaultWidth = 600;
defaultHeight = 600;
// 选择文件夹
Dialog.createNonBlocking("选择目录") ;
Dialog.addDirectory("待处理", "D:/Download/测试", 20 );
Dialog.addDirectory("输出到", "A:/测试数据集/crop", 20);
Dialog.show();
dir = Dialog.getString();
out_dir = Dialog.getString();
//dir = getDirectory("Input directory"); // 选择文件夹
//out_dir = getDirectory("Output directory"); // 选择文件夹
list = getFileList(dir); // 获取文件夹中的文件列表
// 遍历文件夹中的每一张图片
for (i = 0; i < list.length; i++) {
// 只处理图像文件(根据文件扩展名过滤)
if (endsWith(list[i], ".jpg") || endsWith(list[i], ".png") || endsWith(list[i], ".tif") || endsWith(list[i], ".bmp")) {
showProgress(i/(list.length));
open(dir + "/" + list[i]); // 打开图像
originalImage = getImageID();
// 获取当前图像的路径和文件名
currentPath = getDirectory("image"); // 获取当前图像的文件夹路径
fileName = getTitle(); // 获取当前图像的文件名
// 执行裁剪操作
makeRectangle(0, 0, 600, 600); // 初始位置和尺寸
waitForUser("wait for human"); // 等待用户交互(暂停)
Roi.getBounds(x,y,w,h);
print("bounds: ",x,y,w,h);
run("Duplicate...", "Croped");
// run("Crop"); // 执行裁剪
waitForUser("确认裁切结果"); // 等待用户交互(暂停)
// to-do 为裁切后的结果添加缩放预览
// scale = defaultWidth/w>defaultHeight/h?defaultHeight/h:defaultWidth/w;
//
// run("Resize...", "width=0 height=0 constrain average interpolation=Bilinear");
// 设置新的分辨率
// setOption("Scale", true);
// setOption("Interpolation", "Bilinear");
// run("Set Scale...", "x=" + scale*w + " y=" + scale*h + " unit=inch");
//
waitForUser("确认缩放结果"); // 等待用户交互(暂停)
// 查找扩展名
dotIndex = fileName.lastIndexOf('.');
if (dotIndex > 0) { // 确保不是以点开头或没有扩展名
extension = fileName.substring(dotIndex + 1);
}
// 创建新的文件路径
newFilePath = out_dir + fileName; // 将文件名与新路径结合
// 检查 "after" 文件夹是否存在,如果不存在则创建
if (!File.exists(out_dir)) {
File.makeDirectory(out_dir);
}
// 根据文件扩展名确定保存格式
saveAs(extension, newFilePath); // 保存文件
close(); // 关闭当前图像
selectImage(originalImage);
close();
}
}
试试洋芋田图像工具箱呢,图片剪裁可以批量导入,然后设定好参数和比例还有保存目录,一直点确定就行,会自动按列表换图片
差不多已经完成这个imagej的脚本了
Dialog.createNonBlocking("选择目录");
Dialog.addDirectory("待处理", "D:/Download/测试", 20 );
Dialog.addDirectory("输出到", "A:/测试数据集/crop", 20);
Dialog.addNumber("输出宽度", 600);
Dialog.addNumber("输出高度", 600);
Dialog.addCheckbox("跳过输出目录已存在的文件", true);
Dialog.show();
// 选择文件夹
dir = Dialog.getString();
out_dir = Dialog.getString();
// 默认裁剪参数
defaultWidth = Dialog.getNumber();
defaultHeight = Dialog.getNumber();
skipExist = Dialog.getCheckbox();
list = getFileList(dir); // 获取文件夹中的文件列表
items = newArray("预览", "不预览直接裁切", "缩小到预设尺寸并预览", "缩小到预设尺寸并裁切","以宽度为基准,调整高度","以高度为基准,调整宽度", "选区大小 1x", "选区大小 1.5x", "选区大小 2x", "选区大小 3x", "选区大小 4x", "选区大小 6x", "重设选区", "跳过此图", "复制此图","旋转选区","旋转画面90度","旋转画面-90度");
items_save = newArray("保存", "重设选区", "调整选区" ,"跳过此图");
// 遍历文件夹中的每一张图片
for (i = 0; i < list.length; i++) {
// 只处理图像文件(根据文件扩展名过滤)
if (endsWith(list[i], ".jpg") || endsWith(list[i], ".png") || endsWith(list[i], ".tif") || endsWith(list[i], ".bmp")) {
showProgress(i/(list.length));
// 创建新的文件路径
fileName = list[i];
newFilePath = out_dir + fileName; // 将文件名与新路径结合
if (skipExist && File.exists(newFilePath)) {
continue;
}
open(dir + "/" + list[i]); // 打开图像
originalImage = getImageID();
// 获取当前图像的路径和文件名
currentPath = getDirectory("image"); // 获取当前图像的文件夹路径
// fileName = getTitle(); // 获取当前图像的文件名
// 查找扩展名
dotIndex = fileName.lastIndexOf('.');
if (dotIndex > 0) { // 确保不是以点开头或没有扩展名
extension = fileName.substring(dotIndex + 1);
}
state = "预览";
inpreview = 0;
w = defaultWidth;
h = defaultHeight;
x = 0;
y = 0;
scale =1;
// 执行裁剪操作
while(! state.contains("裁切")){
makeRectangle(x, y, w, h); // 初始位置和尺寸
// waitForUser("wait for human"); // 等待用户交互(暂停)
state = "预览";
Dialog.createNonBlocking("对选区操作");
Dialog.addRadioButtonGroup("选择并点OK进入下一步,点击cannel按钮则退出脚本", items, 10, 2, state);
Dialog.show;
state = Dialog.getRadioButton;
// 处理没有选区的情况()
if( selectionType() == -1){
makeRectangle(x, y, w, h);
// print("bounds: is NaN");
} else {
Roi.getBounds(x,y,w,h);
// print("bounds: ",x,y,w,h);
}
if(state == "不预览直接裁切"){
break;
}else if(state.contains("此图")){
break;
}
// 调整选区
if (state == "以宽度为基准,调整高度"){5
h = w * defaultHeight / defaultWidth;
continue;
} else if (state =="以高度为基准,调整宽度"){
w = h * defaultWidth/defaultHeight;
continue;
} else if (state.contains("选区大小")){
// s = state.replace(".+\s([\d\.]+)x","$1");
// s = split(state, " ")[1];
s=substring(state,5);
s = s.replace("x","");
v = parseFloat(s);
print("s: "+s+", v: "+v);
w=defaultWidth*v;
h=defaultHeight*v;
continue;
} else if (state == "重设选区"){
w=defaultWidth;
h=defaultHeight;
x=0;
y=0;
continue;
} else if (state == "旋转画面90度") {
run("Rotate 90 Degrees Right");
continue;
} else if (state == "旋转画面-90度") {
run("Rotate 90 Degrees Left");
continue;
} else if(state=="旋转默认选区"){
v = defaultHeight;
defaultHeight=defaultWidth;
defaultWidth = v;
continue;
} else if(state=="旋转选区"){
v = w;
w=h;
h = v;
continue;
}
// 预览
// "预览", "缩小到预设尺寸并预览", "缩小到预设尺寸并裁切"
run("Duplicate...", "Croped");
cropedImage = getImageID();
// run("Crop"); // 执行裁剪
// waitForUser("确认裁切结果"); // 等待用户交互(暂停)
if(state.contains("缩小")){
if (defaultWidth/w>defaultHeight/h){
scale =defaultHeight/h;
}else{
scale=defaultWidth/w;
}
// run("Resize...", "width=100 height=100 interpolation=Bilinear");
if(scale<1)
run("Size...", "width="+(scale*w)+" height="+(scale*h)+" depth=1 constrain average interpolation=Bicubic");
else {
scale=1;
}
}
if(state.contains("裁切"))
break;
state2="保存";
Dialog.createNonBlocking("对裁切区域操作");
Dialog.addRadioButtonGroup("选择并点OK进入下一步,点击cannel按钮则退出脚本", items_save, 4, 1, state2);
Dialog.show;
state2 = Dialog.getRadioButton;
if(state2=="跳过此图"){
state="跳过此图";
break;
} else if(state2=="调整选区"){
selectImage(cropedImage);
if(cropedImage == getImageID())
close();
continue;
} else if(state2 =="重设选区"){
w=defaultWidth;
h=defaultHeight;
x=0;
y=0;
continue;
}else{
break;
}
}
if(state=="跳过此图"){
close();
continue;
}
// 检查 "after" 文件夹是否存在,如果不存在则创建
if (!File.exists(out_dir)) {
File.makeDirectory(out_dir);
}
// 根据文件扩展名确定保存格式
saveAs(extension, newFilePath); // 保存文件
if(originalImage!=getImageID()){
close(); // 关闭当前图像
selectImage(originalImage);
}
close();
}
}
我用electron写了一个。用到nodejs的sharp库和vue的vue-cropper库,下载地址我放在baidu网盘,你可以直接下载试用,有问题可以发消息。
[交互粗图片裁切工具](通过网盘分享的文件:Batch-cutting-Windows-1.0.0-Setup(1).exe 链接: https://pan.baidu.com/s/1TubN4s8f34S2NeCU5lvhNA?pwd=x44a 提取码: x44a)
软件截图:下载地址在另外一个楼








谢谢你,但是目前使用了imagej的脚本(前边有发出来)
试了下操作逻辑是和我之前设想的一样的,但是离实用还有一些距离:

【批量交互裁图软件 | 快速裁剪 | 【微众软件】分享冷门又好用的小众效率软件】 批量交互裁图软件 | 快速裁剪 | 【微众软件】分享冷门又好用的小众效率软件_哔哩哔哩_bilibili
这就是你要的。
试了下
1.不能直接拖入目录
2.裁剪框既然不能超出图片裁剪,那就限制裁剪框不能超出
3.裁剪框 比例不能继承
4.裁剪框 不能直接设置比例和尺寸
空格裁剪挺方便的
版本已经更新
通过网盘分享的文件:Batch-cutting-Windows-1.0.1-Setup.exe
链接: https://pan.baidu.com/s/1meqgUvZVbDrNizw1qWXXdQ?pwd=m77i 提取码: m77i

你看下能不能这样再完善下:
谢谢
最近比较忙后续不一定有时间更新了
1、w和h可以快速定位到输入框
2、回车可以快速设置裁切尺寸
3、a和<上一张,d和>下一张
4、保存预设优先使用输入框的内容,如果入库框没有内容,用裁切框的尺寸作为预设
5、r可以旋转快速切换宽和高
除了拖拽颗粒度,其他加上了
链接: https://pan.baidu.com/s/1omPONzf099VhZjRvyhpNhw?pwd=4p47 提取码: 4p47
附图:

有个BUG
长和宽没有输入完整 就直接回车或者设定尺寸
会弹出 请输入正确尺寸的 提示框
然后 长宽的输入框 就被锁定无法输入了
(发现切换下软件,或者最小化再恢复就能正常输入了)
感谢反馈,我回头debug一下,送你
,天热多吃西瓜。
又发现一个问题
锁定裁剪框 后
进行缩放 裁剪框会跳回到初始位置
旋转过的裁剪框会恢复(如果旋转过)
这个要求感觉FastStone就可以满足啊,默认是裁剪后自动加载下一张,上一张的裁剪范围也会自动加载,可以微调,可以满足楼主在一楼提出的要求。
怎么操作的呢?没有试出来
谢谢。确实可以
虽然每张要保存和裁剪框调整 比楼上软件麻烦点,
但考虑到FSViewer不到10M的便携性和裁剪功能的使用频率
FSViewer完全够用了