I am trying to "deform" pixels using parabola functions. In the middle of the ROI (the middle line of the rectangle) I want that the parabola will have a more significant curved line (the middle of the rectangle). As you move away from the center/middle line (both right and left) then the parabolas should "fade" and get closer to the shape of a straight line. I am using interpolation (right now the nearest neighbor interpolation) for the goal.
Note: Right now I try to perform it only on grayscale images.
It should look natural like in the next images:


I am using the next formula:
What I manage to do so far:
#include <iostream>
#include <opencv2/opencv.hpp>
#include <cmath>
using namespace std;
int main() {
cv:: Mat originalImage = cv::imread("../dog.jpeg",cv::IMREAD_GRAYSCALE);
cv:: Mat outPutImage = originalImage.clone();
//***** SELECT ROI *****
cv::Rect2d r = cv::selectROI("Select ROI than press Enter/Space",originalImage);
cv::Mat imCrop = originalImage(r);
cv::destroyWindow("Select ROI than press Enter/Space");
double a = 0.001;
double rate_change = 0.00005;
double newX;
for(int y = r.y; y < r.y + r.height ; y++){
if(y <= r.y + r.height/2)
a = a + rate_change;
else {
a = a - rate_change;
//cout << "here" << endl;
}
for(int x = r.x; x< r.x + r.width; x++){
newX = a*pow(double(y-(double(r.y + double(r.height/2)))),2) + double(x);
// // ** NEAREST
//
int nearestNeighborX = round(newX);
if(r.x < nearestNeighborX < r.x + r.width)
outPutImage.at<uchar>(cv::Point2i(x,y)) = originalImage.at<uchar>(cv::Point2i(nearestNeighborX,y));
}
}
I suspect that I need to decide what is a and what is rate_change using the rectangle size or the width-height of the rectangle but Im not sure how to do that.
My output looks unnatural.

