8

I didn't find any examples in openCV to convert a flat image to cylindrical in java, I want it to render the image in 2d not 3d, also didn’t find any example code or book on it. Below is the image of pictures which I want to warp around a cup.

A good book and example code will be much appreciated.

enter image description here

enter image description here

enter image description here

This i have done so far. suggested my @Amitay to make image concave, using this example Wrap image around cylinder but stuck on convertion.

import java.io.File;
import org.bytedeco.javacpp.indexer.UByteBufferIndexer;
import org.bytedeco.javacpp.opencv_core.Mat;
import org.bytedeco.javacpp.opencv_core.*;
import static org.bytedeco.javacpp.opencv_highgui.imshow;
import static org.bytedeco.javacpp.opencv_highgui.waitKey;
import static org.bytedeco.javacpp.opencv_imgcodecs.CV_LOAD_IMAGE_COLOR;
import static org.bytedeco.javacpp.opencv_imgcodecs.imread;

/**
 *
 * @author BTACTC
 */
public class CupWrapping {

    Mat image;
    Mat dstImage;

    int width;
    int height;

    public CupWrapping(File imageFile) {

        image = imread(imageFile.getAbsolutePath(), CV_LOAD_IMAGE_COLOR);

        width = image.size().width();
        height = image.size().height();

        dstImage = new Mat(width, height, image.type());

        UByteBufferIndexer sI = image.createIndexer();
        UByteBufferIndexer sD = dstImage.createIndexer();

        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                Point2f current_pos = new Point2f(x, y);
                current_pos = convert_pt(current_pos, width, height);
                Point top_left = new Point((int) current_pos.x(), (int) current_pos.y()); //top left because of integer rounding

                //make sure the point is actually inside the original image
                if (top_left.x() < 0
                        || top_left.x() > width - 2
                        || top_left.y() < 0
                        || top_left.y() > height - 2) {
                    continue;
                }

                //bilinear interpolation
                float dx = current_pos.x() - top_left.x();
                float dy = current_pos.y() - top_left.y();

                float weight_tl = (float) ((1.0 - dx) * (1.0 - dy));
                float weight_tr = (float) ((dx) * (1.0 - dy));
                float weight_bl = (float) ((1.0 - dx) * (dy));
                float weight_br = (dx) * (dy);

                byte value = (byte) (weight_tl * sI.get(top_left.y(), top_left.x())
                        + weight_tr * sI.get(top_left.y(), top_left.x() + 1)
                        + weight_bl * sI.get(top_left.y() + 1, top_left.x())
                        + weight_br * sI.get(top_left.y() + 1, top_left.x() + 1));
                sD.put(y, x,value);
            }
        }

        imshow("", dstImage);

        waitKey(0);

    }

    public Point2f convert_pt(Point2f point, int w, int h) {
        //center the point at 0,0
        Point2f pc = new Point2f(point.x() - w / 2, point.y() - h / 2);

        //these are your free parameters
        float f = w;
        float r = w;

        float omega = w / 2;
        float z0 = (float) (f - Math.sqrt(r * r - omega * omega));

        float zc = (float) ((2 * z0 - Math.sqrt(4 * z0 * z0 - 4 * (pc.x() * pc.x() / (f * f) + 1) * (z0 * z0 - r * r))) / (2 * (pc.x() * pc.x() / (f * f) + 1)));
        Point2f final_point = new Point2f(pc.x() * zc / f, pc.y() * zc / f);
        final_point.x() = final_point.x() +  w / 2;
       final_point.y() += h / 2;
        return final_point;

    }

    public static void main(String[] args) {

        File imageFile = new File("image/C13.jpg");
        CupWrapping wrap = new CupWrapping(imageFile);
    }

}
Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
Aqeel Haider
  • 603
  • 7
  • 24
  • I don't know the reason for the down voting, if you down vote the question you need to give the specific reason for that. – Aqeel Haider Oct 09 '16 at 15:19
  • I don't know (I'm not the downvoter), but I suspect it's because someone thinks you need to provide more information. See the [tour](https://stackoverflow.com/tour) for details of what folks might be looking for. In this case, I am not sure from your question whether you want to render the cup as a 3-D model textured with the bridge image, or whether you want to render a static image of just that particular cup with the image, or how much of the image should wrap around the cup, or what other libraries you are using, or ... most anything about your situation. Please edit to add detail! :) – cxw Oct 11 '16 at 17:24
  • @cxw Thank you for your comment i edit the question, i think its now more clear. – Aqeel Haider Oct 11 '16 at 21:04
  • Are you trying to render the image onto a 3D model of cup? The question still seems unclear. Can you include the code you have so far that does this? – masad Oct 11 '16 at 23:56
  • I added the code. – Aqeel Haider Oct 12 '16 at 09:23

1 Answers1

7

Look at this answer in Warp Image to Appear in Cylindrical Projection

You only need to change two things:

  1. Because you want convex projection and not concave you need to change the line of code in the function convert_pt.

From:

float zc = (2*z0+sqrt(4*z0*z0-4*(pc.x*pc.x/(f*f)+1)*(z0*z0-r*r)))/(2* (pc.x*pc.x/(f*f)+1));

To

float zc = (2*z0-sqrt(4*z0*z0-4*(pc.x*pc.x/(f*f)+1)*(z0*z0-r*r)))/(2* (pc.x*pc.x/(f*f)+1));
  1. Convert the all the rest of the code form c++ to java.

Good luck

Community
  • 1
  • 1
Amitay Nachmani
  • 3,259
  • 1
  • 18
  • 21
  • @ Amitay Thank you, I'm now converting code from C++ to Java, stuck on image.at(top_left) part, i dont know how to convert this part of code in java. Any suggestion will be helpful. – Aqeel Haider Oct 11 '16 at 21:07
  • It seems that the part you are talking about is just reading values from the original image at certain locations and weighting them based on precomputed weights. So the image.at(top_left) is just image.at(top_left.y,top_left.x). – Binus Oct 18 '16 at 11:03