gpt4 book ai didi

image - 基于 "areas"将图像分割成较小图像的算法

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:28:51 25 4
gpt4 key购买 nike

假设我有一张图片,我想让用户在这张图片内给我一组矩形,然后我想分割这张图片,这样它就可以用在论坛上,或者一个 HTML 文档,矩形将在链接标记之间结束。这意味着,当这个较大的图像被分成较小的图像时,每个水平的分割都必须从一侧到另一侧,而垂直的则不需要这样做。

让我们以这张图片为例:

Example
(来源:s-ul.eu)

我给算法这些矩形:

Example
(来源:s-ul.eu)

我希望它输出不同的图像,通过赋予水平轴更多的重要性来划分(因为论坛和 HTML 文档就像“写作”,如果这有意义的话),像这样:

Example
(来源:s-ul.eu)

如您所见,水平线必须从一边到另一边,而垂直线可以从不同的水平线开始。

然后我会做一些事情来优化它,这样它就不会以 50 亿张图像结束,然后是 bbcode 等,我自己,这不是问题。我正在寻找的是某种可以自己进行除法的算法,这样(这样一条水平线必须从一边到另一边)。

最佳答案

假设您在名为 coords.txt 的文件中有叠加框的坐标,如下所示:

139 49 281 220
306 46 462 225
49 167 170 338
239 142 364 320
427 100 570 291

然后您可以使用 ImageMagick,它安装在大多数 Linux 发行版上,适用于 macOS 和 Windows,只需在终端(命令提示符)的命令行中即可。

首先,获取图像尺寸:

convert scooby.png -format "%w %h" info:
620 365

现在制作另一个相同大小但纯黑色的图像:

convert -size ${w}x${h} xc:black grid.png

现在读取 coords.txt 文件,一次一行,对于其中的每一行,在网格上绘制 4 条白线:

  • 框顶部整个图像的一个完整宽度,
  • 框底部整个图像的全宽
  • 两个根据垂直边

看起来像这样:

while read x1 y1 x2 y2 ; do
convert grid.png -fill white \
-draw "line 0,$y1 $w,$y1" \
-draw "line 0,$y2 $w,$y2" \
-draw "line $x1,$y1 $x1,$y2" \
-draw "line $x2,$y1 $x2,$y2" grid.png
done < coords.txt

这将在 grid.png 中为您提供此内容 - 看起来应该很熟悉:

enter image description here

然后进行“连通分量分析”,找出所有与相同颜色像素 4 连通的像素:

convert grid.png \
-define connected-components:verbose=true \
-define connected-components:area-threshold=100 \
-connected-components 4 -normalize result.png

这会为您提供一张带标签的图像,其中所有您想要的黑色矩形都用一种独特的、越来越亮的颜色进行标识:

enter image description here

我们实际上并不想要那个 - 我们想要的是该命令在终端上的输出,它为您提供所有“连接的组件”,看起来像这样:

Objects (id: bounding-box centroid area mean-color):
0: 620x46+0+0 309.5,22.5 28520 gray(0)
61: 620x26+0+339 309.5,351.5 16120 gray(0)
51: 142x65+428+226 498.5,258.0 9230 gray(0)
49: 124x65+240+226 301.5,258.0 8060 gray(0)
1: 620x293+0+46 308.7,189.8 7930 gray(255)
9: 157x50+463+50 541.0,74.5 7850 gray(0)
47: 120x65+50+226 109.5,258.0 7800 gray(0)
8: 155x50+307+50 384.0,74.5 7750 gray(0)
60: 449x17+171+321 395.0,329.0 7633 gray(0)
57: 255x28+365+292 492.0,305.5 7140 gray(0)
6: 141x50+140+50 210.0,74.5 7050 gray(0)
5: 139x50+0+50 69.0,74.5 6950 gray(0)
11: 141x41+140+101 210.0,121.0 5781 gray(0)
10: 139x41+0+101 69.0,121.0 5699 gray(0)
35: 107x52+463+168 516.0,193.5 5564 gray(0)
13: 120x41+307+101 366.5,121.0 4920 gray(0)
27: 89x52+50+168 94.0,193.5 4628 gray(0)
48: 68x65+171+226 204.5,258.0 4420 gray(0)
15: 107x41+463+101 516.0,121.0 4387 gray(0)
50: 62x65+365+226 395.5,258.0 4030 gray(0)
29: 68x52+171+168 204.5,193.5 3536 gray(0)
56: 124x28+240+292 301.5,305.5 3472 gray(0)
54: 120x28+50+292 109.5,305.5 3360 gray(0)
17: 139x24+0+143 69.0,154.5 3336 gray(0)
33: 62x52+365+168 395.5,193.5 3224 gray(0)
46: 49x65+0+226 24.0,258.0 3185 gray(0)
52: 49x65+571+226 595.0,258.0 3185 gray(0)
32: 57x52+307+168 335.0,193.5 2964 gray(0)
24: 107x24+463+143 516.0,154.5 2568 gray(0)
26: 49x52+0+168 24.0,193.5 2548 gray(0)
36: 49x52+571+168 595.0,193.5 2548 gray(0)
18: 99x24+140+143 189.0,154.5 2376 gray(0)
30: 41x52+240+168 260.0,193.5 2132 gray(0)
59: 120x17+50+321 109.5,329.0 2040 gray(0)
16: 49x41+571+101 595.0,121.0 2009 gray(0)
55: 68x28+171+292 204.5,305.5 1904 gray(0)
34: 34x52+428+168 444.5,193.5 1768 gray(0)
28: 30x52+140+168 154.5,193.5 1560 gray(0)
22: 62x24+365+143 395.5,154.5 1488 gray(0)
14: 34x41+428+101 444.5,121.0 1394 gray(0)
53: 49x28+0+292 24.0,305.5 1372 gray(0)
21: 57x24+307+143 335.0,154.5 1368 gray(0)
31: 24x52+282+168 293.5,193.5 1248 gray(0)
7: 24x50+282+50 293.5,74.5 1200 gray(0)
25: 49x24+571+143 595.0,154.5 1176 gray(0)
19: 41x24+240+143 260.0,154.5 984 gray(0)
12: 24x41+282+101 293.5,121.0 984 gray(0)
58: 49x17+0+321 24.0,329.0 833 gray(0)
23: 34x24+428+143 444.5,154.5 816 gray(0)
2: 306x2+0+47 152.5,47.5 612 gray(0)
20: 24x24+282+143 293.5,154.5 576 gray(0)
38: 120x4+50+221 109.5,222.5 480 gray(0)
44: 107x4+463+221 516.0,222.5 428 gray(0)
4: 157x2+463+47 541.0,47.5 314 gray(0)
3: 155x2+307+47 384.0,47.5 310 gray(0)
39: 68x4+171+221 204.5,222.5 272 gray(0)
40: 66x4+240+221 272.5,222.5 264 gray(0)
42: 62x4+365+221 395.5,222.5 248 gray(0)
41: 57x4+307+221 335.0,222.5 228 gray(0)
37: 49x4+0+221 24.0,222.5 196 gray(0)
45: 49x4+571+221 595.0,222.5 196 gray(0)
43: 34x4+428+221 444.5,222.5 136 gray(0)

每一行对应一张图片。第二个字段告诉您它在图像中的位置,最后一个字段告诉您它的颜色。我们想要黑色的,即 colour=gray(0),因为我们从黑色网格开始。

让我们看一下第三行,它的第二个字段是 142x65+428+226 并且图像上的颜色是半透明的洋红色:

convert scooby.png -fill "rgba(255,0,255,0.5)" -draw "rectangle 428,226 570,291" one.png

enter image description here

很好,现在让我们把每一个都剪下来并保存在自己的图像中:

i=0
for s in "${images[@]}"; do
printf -v name "sub-%04d.png" $i
convert "$image" -crop "$s" "$name"
((i=i+1))
done

让我们看看它们叫什么以及有多少:

ls sub*
sub-0000.png sub-0006.png sub-0012.png sub-0018.png sub-0024.png sub-0030.png sub-0036.png sub-0042.png sub-0048.png sub-0054.png sub-0060.png
sub-0001.png sub-0007.png sub-0013.png sub-0019.png sub-0025.png sub-0031.png sub-0037.png sub-0043.png sub-0049.png sub-0055.png sub-0061.png
sub-0002.png sub-0008.png sub-0014.png sub-0020.png sub-0026.png sub-0032.png sub-0038.png sub-0044.png sub-0050.png sub-0056.png
sub-0003.png sub-0009.png sub-0015.png sub-0021.png sub-0027.png sub-0033.png sub-0039.png sub-0045.png sub-0051.png sub-0057.png
sub-0004.png sub-0010.png sub-0016.png sub-0022.png sub-0028.png sub-0034.png sub-0040.png sub-0046.png sub-0052.png sub-0058.png
sub-0005.png sub-0011.png sub-0017.png sub-0023.png sub-0029.png sub-0035.png sub-0041.png sub-0047.png sub-0053.png sub-0059.png

让我们看看所有的部分都放在一个网格上:

enter image description here

另外,让我们看一下其中一个子图像,注意我们可以看到它在原始图像中的来源:

identify sub-0059.png 
sub-0059.png PNG 49x4 620x365+0+221 8-bit sRGB 139c 931B 0.000u 0:00.000

那个在原始图像中的坐标 0,221。


这是完整的代码。

#!/bin/bash

# Pick up filename from parameter
image=$1

# Get width and height
read w h < <(convert "$image" -format "%w %h" info:)
echo DEBUG: width=$w, height=$h

# Make image same size but black
convert -size ${w}x${h} xc:black grid.png

# Read through coords.txt adding white lines accordingly to "grid.png"
while read x1 y1 x2 y2 ; do
convert grid.png -fill white \
-draw "line 0,$y1 $w,$y1" \
-draw "line 0,$y2 $w,$y2" \
-draw "line $x1,$y1 $x1,$y2" \
-draw "line $x2,$y1 $x2,$y2" grid.png
done < coords.txt
echo DEBUG: You can view sliced grid in file "grid.png"

# Now do a "Connected Components Analysis" and store coordinates of sub-images in array
images=( $(convert grid.png -define connected-components:verbose=true -define connected-components:area-threshold=100 -connected-components 4 -normalize result.png | awk '/(0)/{print $2}') )

# Now chop out images from original according to coordinates
i=0
for s in "${images[@]}"; do
printf -v name "sub-%04d.png" $i
convert "$image" -crop "$s" "$name"
((i=i+1))
done

你只需运行:

./script scooby.png

注意:如果你想让网格的线条稍微粗一些,这样它们就可以偏离几个像素,但仍然分割图像而没有几个像素宽的微小滑动,你可以像这样添加一个笔画宽度:

...
...
# Read through coords.txt adding white lines accordingly
while read x1 y1 x2 y2 ; do
convert grid.png -fill white -stroke white -strokewidth 5 \
-draw "line 0,$y1 $w,$y1" \
...
...

enter image description here

作为替代方案,我想您可以将您从文件中读取的坐标四舍五入到最接近的位置,例如 5 像素(或图像宽度的 1%),以便它们趋向于彼此对齐。

关于image - 基于 "areas"将图像分割成较小图像的算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49719608/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com