如何将图像放入另一个图像

时间:2015-07-12 16:53:01

标签: php image-processing imagemagick

我想将图像放入另一个图像的确切位置。因此我需要

  1. 找到图片中的区域(see also here

  2. 缩放并将叠加图像调整到原始图像文件中。

  3. 示例

    我的原始图片会有类似白页的内容: origianl Image

    现在我必须找到白色矩形并将其替换为过度图像: The overlay example

    结果

    结果看起来应该是这样的: Final result

2 个答案:

答案 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

Imagemagick convert result

它还返回行坐标(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

intersection points result2

就像在这个例子中一样,你不仅要寻找红点,还要寻找红色像素:

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

show founded points and center point

现在我们拥有了最终合成图像所需的全部价值。只缺少一些变量:

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

final automatic resolve image