1

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:

enter image description here

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.

Roy Amoyal
  • 717
  • 4
  • 14
  • the output only looks wrong because your deformation isn't zero at the edges, so it doesn't "fade" nicely. I'm sure you can change your math to account for that. -- I would approach this using a regular grid on the output image, each node pointing to a position in the source image. move the source positions for some nodes. then upsample that with suitable interpolation. then put into `cv::remap`. that ought to give a somewhat smooth result. – Christoph Rackwitz Nov 08 '21 at 00:31
  • if you want it the other way around, with control points in the *output* rather than the input, then that'll be a little more complicated... apis such as OpenGL would be the best solution. just define a mesh of triangles or something, map the texture, then move the vertices. -- this could help https://stackoverflow.com/questions/41703210/inverting-a-real-valued-index-grid – Christoph Rackwitz Nov 08 '21 at 00:57
  • @ChristophRackwitz Im not sure how to change my math for that. I am trying to do it by myself without opencv functions, just math using my own interpolations implementation. – Roy Amoyal Nov 08 '21 at 13:53

0 Answers0