求推荐能批量交互式裁切图片的Windows轻量化软件

预设的初始裁剪尺寸请修改这句:
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改了一晚上还是有致命的问题:

  1. image的脚本不能添加按钮(至少是ijm脚本不行),而 waitForUser(“wait for human”)产生的ok channel效果,仅仅是继续下一行代码和结束脚本(脚本无法直接获取到底点击了哪个按钮来参与复杂逻辑 当然可以再加复选框,用复选框+按钮来充当自定义按钮,但是这难道不是很奇怪嘛,而且一晚上已经过去了,得明天再试了)。这就导致一个图片裁切后必须保存,不可以有复杂逻辑。一旦点击取消,就完全没有下一个图片的事情了。

  2. 缺少了缩放的处理逻辑。同上,因为没有复杂逻辑的原因,也不能预览到缩放结果并做相应对策。

// 默认裁剪参数
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 Macro,可能比较简陋,
其他语言应该都比较完备吧。

试试洋芋田图像工具箱呢,图片剪裁可以批量导入,然后设定好参数和比例还有保存目录,一直点确定就行,会自动按列表换图片

洋芋田

差不多已经完成这个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)

软件截图:下载地址在另外一个楼
1.png
2.png
3.png
4.png
5.png
6.png
7.png
8.png

谢谢你,但是目前使用了imagej的脚本(前边有发出来)

试了下操作逻辑是和我之前设想的一样的,但是离实用还有一些距离:

  1. 无法直接设置裁切框的尺寸,关键在于调整裁切框大小后,下一个图无法快速恢复裁切框大小
  2. 缺少了默认缩放的考量。根据我的观察,现在框是窗口的固定尺寸,而图片是自动适应控件的尺寸。这就导致图大时,默认裁切的尺寸就大,图小时默认裁切尺寸小。实际上是需要无论图大小,优先裁切出预设的尺寸的。
  3. 部分图片加载后会显示为黑色图,由于未能显示图片名称,不太能确认到原因
    image.png

【批量交互裁图软件 | 快速裁剪 | 【微众软件】分享冷门又好用的小众效率软件】 批量交互裁图软件 | 快速裁剪 | 【微众软件】分享冷门又好用的小众效率软件_哔哩哔哩_bilibili
这就是你要的。

试了下
1.不能直接拖入目录
2.裁剪框既然不能超出图片裁剪,那就限制裁剪框不能超出
3.裁剪框 比例不能继承
4.裁剪框 不能直接设置比例和尺寸

空格裁剪挺方便的

版本已经更新
通过网盘分享的文件:Batch-cutting-Windows-1.0.1-Setup.exe
链接: https://pan.baidu.com/s/1meqgUvZVbDrNizw1qWXXdQ?pwd=m77i 提取码: m77i
Snipaste_2025-04-30_14-07-24.png

你看下能不能这样再完善下:

  1. 在宽高输入框内输入数字后,回车能直接应用对应尺寸,不需要额外点击一次按钮.
  2. 能预设多组长宽,快速应用对应的预设
  3. 绑定更多快捷键,r 旋转选择框90度,ad<>切换上下文件
  4. 快速调整当前的框的尺寸(不是默认框) 我想到有两种操作方式, 能实现其1即可,优先方式1:
  • 方式1 增加一个拖拽粒度的数值选项,比如粒度是50,那拖拽框的结果会变成150 200 250这样变化,而不是150 151 152这样连续变化。 增加一个锁定宽高比的勾选框。
  • 方式2 像cad的命令一样,输入w激活宽度设置,输入数字调整宽度,回车完成修改,esc取消修改。同理输入h激活高度设置。

谢谢

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

有个BUG
长和宽没有输入完整 就直接回车或者设定尺寸
会弹出 请输入正确尺寸的 提示框
然后 长宽的输入框 就被锁定无法输入了
(发现切换下软件,或者最小化再恢复就能正常输入了)

感谢反馈,我回头debug一下,送你 :watermelon:,天热多吃西瓜。

又发现一个问题
锁定裁剪框 后
进行缩放 裁剪框会跳回到初始位置
旋转过的裁剪框会恢复(如果旋转过)

这个要求感觉FastStone就可以满足啊,默认是裁剪后自动加载下一张,上一张的裁剪范围也会自动加载,可以微调,可以满足楼主在一楼提出的要求。

怎么操作的呢?没有试出来

你再试试……我录的时候打开的是文件夹里的第一张图片,按理说裁剪完保存,按下一页应该是第二张图片,结果FastStone默认这个图片是最后一张,所以就裁完一张,往前找前面的一张,你可以研究下FastStone的默认排序是什么样的,因为这个录屏也能看懂,就懒得再弄了。重点是裁剪后选择“无损剪切到文件”

谢谢。确实可以
虽然每张要保存和裁剪框调整 比楼上软件麻烦点,
但考虑到FSViewer不到10M的便携性和裁剪功能的使用频率
FSViewer完全够用了