Create image from bearings and ranges

I am trying to convert a list of bearings and ranges to an image.
I basically have an image:
sonar
with rows corresponding to range (~0 to ~400cm) and column to bearings (~-65 to ~65deg).
I am already able to manually convert it to

but there is a lot of gaps between the measurement. I have tried to use OpenCV methods like polarWarp but have not been able to obtain a satisfying result.

seems the second figure was not posted, here it is: Figure_1

warpPolar is the correct function to transform this.

please provide a Minimal Reproducible Example (including data) so we can investigate any issues. is the first picture suitable data?

I only needed to zero-pad the input to have a full circle of data…

if you need more precise control over the mapping, of course you can always calculate an index map yourself and then use remap()

yes, the first picture is good. How did you achieve this result? Is this zero pad operation time consuming?

copyMakeBorder, costs one copy. the downside is that this can only add whole pixels worth of data, so if you need perfect accuracy in fractions of a degree, you’d need to spend a little thought on everything.

if you’re looking for maximum speed, or need to control the math fairly precisely (by pixels/subpixel), you’d want to compare that against a custom xymap suitable for remap(). warpPolar might be using the special case math (vs. remap) to its advantage… or maybe precomputing the map makes it cheaper.

Could you share how you did it? I cannot manage to do it

you say the data is -65 to +65 degrees, so that is 130 degrees, and that is 256 pixels, right?

now calculate how many pixels would be 360 degrees. that’s 256 / 130 * 360

that is the size you need to pad to. the arguments to copyMakeBorder are derived from those values.

then you would use rotate() to rotate the picture. the top edge, representing the center of the polar image, needs to go to the left because that’s the orientation required by warpPolar.

then you just give warpPolar some sensible arguments.

if you have problems with specific code, I’ll take a look.

I am doing this

total_pix = int(((256 / 130 * 360)-256)/2)
source = cv2.rotate(source, cv2.ROTATE_90_COUNTERCLOCKWISE)
source = cv2.copyMakeBorder(source, total_pix, total_pix, 0, 0, cv2.BORDER_CONSTANT)
source = cv2.warpPolar(source, (409,800), (source.shape[0]/2, 0), 409, cv2.INTER_LINEAR | cv2.WARP_FILL_OUTLIERS)

but does not result in anything good

you missed WARP_INVERSE_MAP

the warp can go both ways.

that’s bad. put the center further down. it’s at the top now. put it at half height. also, the order is (x,y), and source.shape[0] (height, ~709) has no meaning in the output. the output is purely shaped according to radius.