1

I'm working on a floor design app where the user can import a floor texture and the app will place the texture on to a room image. I've managed to transform the perspective of the floor image so that it matches the room image - thanks to this answer, but I'm now stuck on scaling the floor image to match the room image dimensions. I know the real dimensions of the wooden floor (177mm x 1220mm per plank), I know the height of an object in the room image (height of white tile near sink is 240mm) and I know the distance between the camera and the white tile (roughly 2500mm). The room image size is 2592x1936, the floor image size is 1430x1220. The room image was taken with from an iPad air camera to which I can't seem to find any info regarding the focal length and sensor size, the nearest I could find was a 3.3 focal length with 3.6mm sensor height (this may be where I'm going wrong).

I tried using this equation

The numbers I plugged in to the equation, 2662 = (3.3 240 x 1936) / (160 x 3.6) I then tried to work out the object height for a wooden plank in the floor image, (3.3 x 1220 x 1936) / (2662 x 3.6) = 813 px I then divided the image height by the object height to get a ratio = 2.38.
This image is with a 2.38 ratio applied to the floor image which isn't quite right. enter image description here

I know I'm going wrong somewhere or going the complete wrong way about it, hope somebody can point me in the right direction. Thanks

Community
  • 1
  • 1
WagglyWonga
  • 341
  • 3
  • 14
  • This formula will only work for object lengths parallel to the camera sensor. I would utilize the homography that you probably already have for texturing. Invert the homography to get a mapping from screen space to texture space. Then, you can map any line segment on the floor in the image to the corresponding representation in texture coordinates. By comparing the resulting line segment's length to the target length, you can derive the scaling of your texture. – Nico Schertler Aug 19 '16 at 12:28

1 Answers1

1

I'd extend the lines of the tile till they touch the edge where the back wall meets the floor. Using this technique you can transfer a length from the wall plane to an equal length in the floor plane. So at that point, all you have to do is match lengths along a single line, namely the lengths between planks and the lengths between your transferred points. But you have to do this in a projectively consistent fashion. The most versatile tool for projective measurements is the cross ratio. An application very similar to what you have here is described in How to calculate true lengths from perspective projection on Math SE. If your vanishing point on that line where the walls meet is indeed at infinity (which appears to be approximately the case in your setup), you can get by with some simpler computations, but unless you can guarantee that this will always be the case, I'd not rely on that.

The above will help you adjust the scale in one direction only. The direction perpendicular to that is still open, though. In your exaple that would be the depth direction, the direction away from the camera. Do you have any reference points for that direction? It looks to me as though you might be able to use one complete tile on the left wall, before the window starts. But depending on how the corner between the two walls is tiled, that might be slightly off.

Illustration

To illustrate these ideas, look at the picture above. Since the red lines appear almost horizontal, seeing the effects of perspective there is pretty hard. Therefore I'll do the other direction. Suppose the tile in the corner is indeed the same visible size as all the other tiles on the wall. So you know the real world distance between A1 and B1. You project along the blue vertical lines (vertical in the real world, not neccessarily the image) down to A2 and B2 which is where the left wall plane meets the floor plane.

Why do they meet there? Well, the lines A1,A2 is where the left all meets the back wall. The line A2,A3 is where the back wall meets the floor. Both of these plane intersections are actually visible at least in part, which made drawing the lines possible. So at A2 all three planes meet, and connecting that to the far point F gives the third edge, where the left wall meets the floor.

Since the segments A1,B1 and A2,B2 are just vertically transported versions of one another in the real world, they have equals length. That transportation was along the left wall in the vertical direction. Now transport them again, this time in the floor plane and in the left-right direction. You do so using the red lines, which are either parallel or meet at a point (which is pretty far away in this example). These red lines A2,A3 and B2,B3 are parallel in the real world, and their distance is still the edge length of that tile.

Now start measuring something, e.g. distance between C and D. To do that, compute the cross ratio (F,A3;B3,C) which expresses the distance from A3 to C, expressed in multiples of the distance from A3 to B3, and using F as the point at infinity. Do the same for D, and then the difference will be the length from C to D, expressed in multiples of the distance from A3 to B3. So the distance between C and D is 4.42 tile edge lengths in this example. Scale your image to fit this figure.

Community
  • 1
  • 1
MvG
  • 57,380
  • 22
  • 148
  • 276
  • Thanks @MvG, after reading your helpful link I think I know what I need to do, I'm a bit confused though of what I need to do to "transfer a length from the wall plane to an equal length in the floor plane" - I've extended lines from the tiles to where the wall meets the floor but not sure what I do after that? – WagglyWonga Aug 22 '16 at 10:07
  • @WagglyWonga: I've expanded my answer to add an example. Hope this clarifies how to transfer lengths between planes. – MvG Aug 22 '16 at 10:55
  • Thank you, it makes sense to me now. As a check though, would I be right in thinking I can measure the width of a floor plank where the floor meets the back wall and it should match the tile width, eg. Tile width is 320mm, plank is 177mm, tile width in pixels is 150, so plank width in pixels should be around 83? – WagglyWonga Aug 22 '16 at 11:27
  • @WagglyWonga: That would be correct, *if* the blue vertical lines are parallel in your picture and *if* the plank you are measuring is either vertically directly below the tile or the red lines are parallel. If the vertical lines are not parallel, you need to use the distance two such lines have at the floor, not at the place where the tile originally is. And if the plank is not directly below the tile and the red lines are not parallel, then you have to use cross ratios or similar to account for the perspective distortion instead of just counting pixels. – MvG Aug 22 '16 at 13:03
  • Sorry @MvG, would you mind showing me how you got to 4.42, I can't figure it out myself. – WagglyWonga Aug 22 '16 at 15:01
  • I typed the formula you see into Cinderella, a geometry system which is based on projective geometry and therefore doesn't care whether the points in question (F in this case) are finite or at infinity. Behind the scenes it would use something like (A,B;C,D)=[ACX][BDX]/[ADX][BCX] where […] denotes a 3×3 determinant using homogeneous coordinates of the points, and X is any point *not* on the line spanned by these four points. Might e.g. be the point at infinity perpendicular to the line. There is also a formula using 2×2 determinants but then you need a coordinate conversion to the line first. – MvG Aug 22 '16 at 15:50