Calculate the area of a trapezoid from picture while adjusting for angle
Here's a general math problem I was hoping someone could help me with. My app has the user take a picture of a roof and then mark the perimeter of the roof. I would like to calc开发者_C百科ulate the area of the trapezoid drawn by the user. However, since roofs are angled, I need adjust for that fact.
Can anyone point me in the right direction? My math skills are quite rusty (and were never particularly strong).
-- a picture might help. A user might outline the roof as shown below with the red line. But if the roof could be magically rotated to be perpendicular with the ground, it would look likely fill the space closer to the blue line. So, what I'm wondering is, is there any math that I can do that might accomplish this? (I realize there are other options such as calculating the length of two sides using separate pictures and multiplying them.)
Getting the area of the actual roof from a mere picture is impossible. You couldn't know whether the picture was taken at five or fifty meters, so a roof that looks tiny in the picture could be enormous. You would need a depth map to get the actual size of the roof, and even that would be tricky.
This is possible, but only if you can add a host of constraints to the situation where the picture is being taken:
- If you know the opening angle of the lens used to take the picture, and you know the exact distance to the roof at the time the picture was taken (distance between camera and gutter), and the picture was taken exactly as in your sample with the roof perpendicular to the camera axis, and the camera pointed directly at the horizontal center of the gutter, and you know for certain the roof is rectangular, then it is surprisingly simple. If you don't mind being off by something between 10 and 25%. (depending on the accuracy of various measurements).
- If you can't know the opening angle of the lens (because the picture is not taken by a camera you control, or because the picture is taken by a camera with a zoom lens) but there is an object of known size, a known distance from the camera in the image then it is still surprisingly simple, because you can determine the opening angle from the known object. The object needs to be significantly large in the image (50% of the horizontal width in the image or so) but it can be closer to the photographer, so it won't have to be as large as the roof.
- If you can't control the exact position from which the picture was taken (i.e. it won't be taken directly opposite the center of the gutter) your accuracy will be way off.
If you know the horizontal opening angle alpha
of the camera, the distance Dgut
between camera and gutter, the width of the gutter in pixels Wgut
and the width of the image in pixels Wim
, then you can determine the approximate length of the gutter Lgut
from:
Dpixgut= Wim/(tan(alpha/2)) # distance to the gutter in pixel space
tan(anggut) = Wgut/Dpixgut # tan of half "opening angle" of the gutter
Lgut= 2*tan(anggut)*Dgut
Because you know Ltop
(the lenght of the top of the roof) equals Lgut
(this is one of the constraints) you can use the width of the top in pixels Wtop
to calculate the distance to the top of the roof Dtop
:
Dpixtop=Wim/(tan(alpha/2)) #dist to top in pixel space
tan(angtop)=Wtop/Dpixtop
Dtop=Ltop/(2*tan(angtop)) #dist to roof in real space (note that Ltop=Lgut)
Dtop-Dgut
gives you a rough estimate of the length Lroof
of the roof, so Dgut*Lroof
is a rough approximation of the area. To be more exact you have to include some calculations similar to the ones above to determine the height of the gutter and the top of the roof above the camera axis, and then adjust Lroof
for that.
Note that this approximation is just that. An approximation. Try some examples from roofs for which you know the area to get a feel for the accuracy (which could be surprisingly bad I fear).
精彩评论