Tough problem! Even if you could crop a triangle, how do you know where to crop it and at what angle, if you don't know whether the box is turned or not? Once you find out if it is turned or not, then what are you going to do with that information? What is your ultimate goal?
What average graylevel value do you want from the RGB channels - that at each pixel or that of the whole image?
A bit more information may give us a better idea of what you are trying to do and perhaps there is another way to approach it.
how to detected white triangular lower right corner
- fmw42
- Posts: 25562
- Joined: 2007-07-02T17:14:51-07:00
- Authentication code: 1152
- Location: Sunnyvale, California, USA
Re: how to detected white triangular lower right corner
Here is a bash script that will determine if your box is turned. A perfectly rectangular orientation will give a result of zero or black. Any distortion (rotation) will produce a larger result. Your image gives a value of about 15%.
The script processes the image to binary format (white for box and black for background). It then processed the binary image to average all columns together to form one column (and stretches the result to full white and black range). If the box were rectangular, the column would have only white and black values. But as the box is rotated, some rows average to pixels that are grayscale values between black and white. So we next threshold the column to find the area of pure white (the minimum inside rectangular area of the box). Then we average the column down to one pixel and likewise the thresholded column to one pixel and form the ratio fo the difference to the thresholded value abs(u-v)/v. For a perfectly rectangular box, u=v and we get a result of 0. The value of the resulting one-pixel image is printed out using -fx. So you might get a name (black, gray, etc) or you could get rgb(r%,g%,b%) format results. For your image, I got rgb(14.5937%,14.5937%,14.5937%)
Here is the script. You may also want to modify it to process the image first to one row instead of one column in case the parallel edges are horizontal rather than vertical on your box or none of them are parallel.
#!/bin/bash
#
infile="boxart.jpg"
threshold=10
coords="0,0"
# set directory for temporary files
dir="." # suggestions are dir="." or dir="/tmp"
tmpA="$dir/boxart_$$.mpc"
tmpB="$dir/boxart_$$.cache"
tmp0="$dir/boxart_0_$$.png"
tmp1="$dir/boxart_1_$$.png"
tmp2="$dir/boxart_2_$$.png"
tmp3="$dir/boxart_3_$$.png"
tmp4="$dir/boxart_4_$$.png"
# comment out trap lines below to keep the temporary images for viewing
trap "rm -f $tmpA $tmpB $tmp0 $tmp1 $tmp2 $tmp3 $tmp4; exit 0" 0
trap "rm -f $tmpA $tmpB $tmp0 $tmp1 $tmp2 $tmp3 $tmp4; exit 1" 1 2 3 15
if convert -quiet -regard-warnings "$infile" +repage "$tmpA"
then
width=`identify -format %w $tmpA`
height=`identify -format %h $tmpA`
else
echo "--- FILE $infile DOES NOT EXIST OR IS NOT AN ORDINARY FILE, NOT READABLE OR HAS ZERO SIZE ---"
exit 1
fi
# make exterior transparent and interior white
convert $tmpA -fuzz $threshold% -fill transparent -draw "matte $coords floodfill" \
-fill white -colorize 100% $tmp0
# change exterior to black
convert $tmp0 -channel RGBA -fill black -opaque none $tmp0
# average binary image to one column and stretch graylevels to full range
convert $tmp0 -filter box -resize 1x$height! -normalize $tmp1
# threshold to show only where solid white region (make black and gray to black)
convert $tmp1 -threshold 65534 $tmp2
# average tmp1 and tmp2 each vertically to one pixel
convert $tmp1 -filter box -resize 1x1! $tmp3
convert $tmp2 -filter box -resize 1x1! $tmp4
# generate statistics
# statistics will be black or zero if box is a perfect rectangle and not rotated or distorted
# statistics will be larger the more the box is rotated
convert $tmp3 $tmp4 -fx "abs(u-v)/v" -format '%[pixel:u.p{0,0}]' info:
Hope this helps.
Fred
The script processes the image to binary format (white for box and black for background). It then processed the binary image to average all columns together to form one column (and stretches the result to full white and black range). If the box were rectangular, the column would have only white and black values. But as the box is rotated, some rows average to pixels that are grayscale values between black and white. So we next threshold the column to find the area of pure white (the minimum inside rectangular area of the box). Then we average the column down to one pixel and likewise the thresholded column to one pixel and form the ratio fo the difference to the thresholded value abs(u-v)/v. For a perfectly rectangular box, u=v and we get a result of 0. The value of the resulting one-pixel image is printed out using -fx. So you might get a name (black, gray, etc) or you could get rgb(r%,g%,b%) format results. For your image, I got rgb(14.5937%,14.5937%,14.5937%)
Here is the script. You may also want to modify it to process the image first to one row instead of one column in case the parallel edges are horizontal rather than vertical on your box or none of them are parallel.
#!/bin/bash
#
infile="boxart.jpg"
threshold=10
coords="0,0"
# set directory for temporary files
dir="." # suggestions are dir="." or dir="/tmp"
tmpA="$dir/boxart_$$.mpc"
tmpB="$dir/boxart_$$.cache"
tmp0="$dir/boxart_0_$$.png"
tmp1="$dir/boxart_1_$$.png"
tmp2="$dir/boxart_2_$$.png"
tmp3="$dir/boxart_3_$$.png"
tmp4="$dir/boxart_4_$$.png"
# comment out trap lines below to keep the temporary images for viewing
trap "rm -f $tmpA $tmpB $tmp0 $tmp1 $tmp2 $tmp3 $tmp4; exit 0" 0
trap "rm -f $tmpA $tmpB $tmp0 $tmp1 $tmp2 $tmp3 $tmp4; exit 1" 1 2 3 15
if convert -quiet -regard-warnings "$infile" +repage "$tmpA"
then
width=`identify -format %w $tmpA`
height=`identify -format %h $tmpA`
else
echo "--- FILE $infile DOES NOT EXIST OR IS NOT AN ORDINARY FILE, NOT READABLE OR HAS ZERO SIZE ---"
exit 1
fi
# make exterior transparent and interior white
convert $tmpA -fuzz $threshold% -fill transparent -draw "matte $coords floodfill" \
-fill white -colorize 100% $tmp0
# change exterior to black
convert $tmp0 -channel RGBA -fill black -opaque none $tmp0
# average binary image to one column and stretch graylevels to full range
convert $tmp0 -filter box -resize 1x$height! -normalize $tmp1
# threshold to show only where solid white region (make black and gray to black)
convert $tmp1 -threshold 65534 $tmp2
# average tmp1 and tmp2 each vertically to one pixel
convert $tmp1 -filter box -resize 1x1! $tmp3
convert $tmp2 -filter box -resize 1x1! $tmp4
# generate statistics
# statistics will be black or zero if box is a perfect rectangle and not rotated or distorted
# statistics will be larger the more the box is rotated
convert $tmp3 $tmp4 -fx "abs(u-v)/v" -format '%[pixel:u.p{0,0}]' info:
Hope this helps.
Fred