我想将图像放入另一个图像的确切位置。因此我需要
找到图片中的区域(see also here)
缩放并将叠加图像调整到原始图像文件中。
示例
我的原始图片会有类似白页的内容:
现在我必须找到白色矩形并将其替换为过度图像:
结果
结果看起来应该是这样的:
答案 0 :(得分:1)
我原以为你能够解决方程,但我可以告诉你如何被卡住。
让我们看看列出的前两行。它们是直线,因此可以用形式
表示y = mx + c
其中c
是y轴截距,m
是线的渐变。
因此,对于第一行,截距或c
显然是198,因为它在那里穿过x轴。如果我们输入其他一些值(我会忽略小数,因为它们只是混淆了这个概念),你会得到
63 = 1280m + 198
所以,第一行的等式是
y = -135x + 198
-----
1280
可以使用类似的三角形来发现第二行以获得y轴截距,或c
所以
38 = 802
--- ---
720 c
表示
c = -802 * 720
----------
38
如果我们再次将我们为第二行列出的值放入公式中,我们得到
720 = 840 m - 802*720
-------
32
表示
m=18.95
和第二行的等式是
y=18.95x -15196
所以,如果我们将两个y值设置为相等,那么它们必须符合
的情况-135x + 198 = 18.95x - 15,196
-----
1280
-135x = 23,687x + 19,242,500
因此x = 807并且在第1行的等式中代入,y = 112。
所以前两行相交于112,807。
我会让你做其他三个......
答案 1 :(得分:0)
使用Imagemagick(> 6.8)我可以使用以下命令检测或多或少地检测白色矩形:
convert example.jpg -threshold 40% -canny 0x1+10%+30% \
\( +clone -background none \
-fill red -stroke red -strokewidth 2 \
-hough-lines 50x50+80 -write lines.mvg \
\) -composite result.png
它还返回行坐标(lines.mvg)。
# Hough line transform: 50x50+80
viewbox 0 0 1280 720
line 0,198.011 1280,63.4774 # 280
line 802.382,0 840.115,720 # 97
line 0,675.347 1280,518.183 # 238
line 138.716,0 201.708,720 # 191
稍后我想为mark-setchell answer建议的公式实施解决方案。
你可以让imagemagick寻找交叉点......
convert example.jpg -threshold 40% -canny 0x1+10%+30% \
\( +clone -background none \
-fill red -stroke red -strokewidth 1.2 \
-hough-lines 50x50+80 \
\) -composite -fuzz 50% -fill black -opaque white \
-morphology HMT LineJunctions result2.png
就像在这个例子中一样,你不仅要寻找红点,还要寻找红色像素:
convert result2.png txt:- | egrep "red|srgb\(2[45][1234567890]"
# 808,112: (255, 0, 0) #FF0000 red
# 807,113: (254, 0, 0) #FE0000 srgb(254,0,0)
# 809,113: (254, 0, 0) #FE0000 srgb(254,0,0)
# 155,183: (245, 0, 0) #F50000 srgb(245,0,0)
# 832,572: (255, 0, 0) #FF0000 red
# 196,652: (247, 0, 0) #F70000 srgb(247,0,0)
现在是时候通过积分来清理......
points=`convert result2.png txt:- | egrep "red|srgb\(2[45][1234567890]" | sed -n 's/^\([0-9]*,[0-9]*\).*$/\1/p'`
close=100
clean=()
distance()
{
echo $(( ($1 - $3) * ($1 - $3) + ($2 - $4) * ($2 - $4) ))
}
while read x1 y1
do
ok=1
for point in "${clean[@]}"
do
echo "compare $x1 $y1 with $point"
set -- $point
if [[ $(distance $x1 $y1 $1 $2) -le $close ]]
then
ok=0
break
fi
done
if [ $ok = 1 ]
then clean+=("$x1 $y1")
fi
done < <( echo -e "$points" | tr ',' ' ' | sort -u )
echo "Clean:"
printf "%s\n" "${clean[@]}" | tr ' ' ','
edge_points=`printf "%s\n" "${clean[@]}" | tr ' ' ','`
订购它们......
# get Center
centerx=0
centery=0
for point in $edge_points;
do
x=$(echo "$point" | cut -d, -f1)
y=$(echo "$point" | cut -d, -f2)
if [ $centerx -eq 0 ]
then
centerx=$((x))
centery=$((y))
else
centerx=$(( centerx+x ))
centery=$(( centery+y ))
fi
i=$((i+1))
done
centerx=$(( centerx/i ))
centery=$(( centery/i ))
centercircle="circle $((centerx-1)),$((centery-1)) $((centerx+1)),$((centery+1))"
echo "final center point $centercircle"
# Determine top-left, bottom-left, top-right, and bottom-right corner
top=()
bot=()
for point in $edge_points;
do
x=$(echo "$point" | cut -d, -f1)
y=$(echo "$point" | cut -d, -f2)
if [[ $y -le $centery ]]
then
top+=("$x $y")
else
bot+=("$x $y")
fi
done
echo "top points:"
printf "%s\n" "${top[@]}" | tr ' ' ','
echo "botten points:"
printf "%s\n" "${bot[@]}" | tr ' ' ','
top_points=`printf "%s\n" "${top[@]}" | tr ' ' ','`
bot_points=`printf "%s\n" "${bot[@]}" | tr ' ' ','`
[ $(echo ${top[0]} | cut -f1 -d ' ' ) -gt $(echo ${top[1]} | cut -f1 -d ' ' ) ] && tl=${top[1]} || tl=${top[0]}
[ $(echo ${top[0]} | cut -f1 -d ' ' ) -gt $(echo ${top[1]} | cut -f1 -d ' ' ) ] && tr=${top[0]} || tr=${top[1]}
[ $(echo ${bot[0]} | cut -f1 -d ' ' ) -gt $(echo ${bot[1]} | cut -f1 -d ' ' ) ] && bl=${bot[1]} || bl=${bot[0]}
[ $(echo ${bot[0]} | cut -f1 -d ' ' ) -gt $(echo ${bot[1]} | cut -f1 -d ' ' ) ] && br=${bot[0]} || br=${bot[1]}
echo "lt: $tl"
echo "lr: $tr"
echo "bl: $bl"
echo "br: $br"
clean_ordered=()
clean_ordered+=("$tl")
clean_ordered+=("$tr")
clean_ordered+=("$br")
clean_ordered+=("$bl")
edge_points=`printf "%s\n" "${clean_ordered[@]}" | tr ' ' ','`
# draw result
radius=2
nr=1
circles=$(for point in $edge_points; do
x=$(echo "$point" | cut -d, -f1)
y=$(echo "$point" | cut -d, -f2)
# use IM to do some floating point math, EG: y2=$y+$radius
y2=$(convert xc: -format '%[fx:'"$y"'+'"$radius"']' info:)
echo "circle $x,$y $x,$y2"
done)
echo "$circles"
text=$(for point in $edge_points; do
x=$(echo "$point" | cut -d, -f1)
y=$(echo "$point" | cut -d, -f2)
x=$((x+5))
y=$((y+5))
echo "text $x,$y \"$nr\""
nr=$((nr+1))
done)
# Draw blue circles on the 4 points and the center point.
convert result2.png \
-draw "fill none stroke blue $circles " \
-draw "fill none stroke blue $centercircle" \
-pointsize 20 \
-draw "fill blue stroke blue $text " \
result3.png
现在我们拥有了最终合成图像所需的全部价值。只缺少一些变量:
points_a=`printf "%s\n" "${clean_ordered[0]}" | tr ' ' ','`
points_b=`printf "%s\n" "${clean_ordered[1]}" | tr ' ' ','`
points_c=`printf "%s\n" "${clean_ordered[2]}" | tr ' ' ','`
points_d=`printf "%s\n" "${clean_ordered[3]}" | tr ' ' ','`
orgi_size=$(identify -format "%[fx:w]x%[fx:h]" test/example.jpg)
owidth=$(identify -format "%[fx:w]" test/overly.png)
oheight=$(identify -format "%[fx:h]" test/overly.png)
现在我们可以绘制最终结果,因此我们使用-distort perspective
方法(表示2.问题的答案):
convert \
-verbose \
example.jpg \
\( overly.png \
-background none \
-gravity NorthWest \
-extent $orgi_size \
-alpha set -virtual-pixel transparent \
-distort Perspective "0,0 $points_a $owidth,0 $points_b $owidth,$oheight $points_c 0,$oheight $points_d" \) \
-composite result4.jpg