问题
I am trying to recreate the view of a camera from a spherical projection, so that the resulting image is orthographic (straight lines in reality equate to straight lines in the image space).
I have used the sphericalWarper warp function before with success:
detail::SphericalWarper Projection = detail::SphericalWarper(((360.0/PX2DEG)/PI)/2.0);
Mat SrcProj;
Projection.warp(Src, CameraIntrinsics, Rotation, INTER_LINEAR, 0,SrcProj);
But when I use the function warpBackward
, it requires me to specify the destination Mat size. It seems like if its not a very specific size, it causes an error. I dug into the library files and found the assert which sends the error, and found this (snippet from warpers_inl.hpp):
void RotationWarperBase<P>::warpBackward(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode, Size dst_size, OutputArray dst)
{
projector_.setCameraParams(K, R);
Point src_tl, src_br;
detectResultRoi(dst_size, src_tl, src_br);
Size size = src.size();
CV_Assert(src_br.x - src_tl.x + 1 == size.width && src_br.y - src_tl.y + 1 == size.height);
unfortunately detectResultRoi
is a protected function so im a little stuck on how to find the correct size of the destination image.
Any help will be much appreciated, thanks!
====================================Edit==================================== The Src size can be calculated using the warpRoi function, which is public.
Mat SrcProj=Mat(480,640,CV_8UC3,Scalar(0,0,0));
Rect WindowSize=Projection.warpRoi(SrcProj.size(),CameraIntrinsics,Rotation);
Above I defined my output size, then used warpRoi to find the Src size (or window size). Now you have the size you can cut a Mat of this size from the Src image (or resize it) and then use the warpBackward function without issue.
回答1:
You can not access detectResultRoi
directly, but you can inherit it and use as you want in your own class.
class MySphericalWarper : private SphericalWarper
{
public:
using SphericalWarper::warp;
void unwarp( ... ) {
...
detectResultRoi( ... );
...
}
...
};
Then just use your implementation.
MySphericalWarper warper( ... );
Mat proj, unproj;
warper.warp(src, ... , proj);
// warp backward
warper.unwarp(proj, ... , unproj);
But I don't think that detectResultRoi
will be usefull to detect the unprojected image size. Actually you need to do the opposite, as detectResultRoi
calculates the spherical image region where the projected image will be.
You need to know where the projection pixels are in the spherical image. Then you can calculate the size of unprojected image: take difference between right-most & left-most, highest & lowest unprojected pixels' positions among all border pixels of that (usually not rectangular) region. This positions can be obtained with SphericalWarper::projector_.mapBackward()
. projector_
member is protected
too, so you need to use it the same way as described above for detectResultRoi
.
This size is the same, as the size of the image you warp
, if you want to warp backwards the result (or modified result, you can change pixel values, this does not change the mapping of pixel positions) of warp
.
detail::SphericalWarper projection(((360.0/PX2DEG)/PI)/2.0);
Mat proj, unproj;
projection.warp(src, CameraIntrinsics, Rotation, INTER_LINEAR, 0, proj);
// paint on proj or something ...
projection.warpBackward(proj, CameraIntrinsics, Rotation, INTER_LINEAR, 0, src.size(), unproj);
来源:https://stackoverflow.com/questions/56074645/opencv-spherical-projection-warping-and-unwarping