Hello I’ve come across the following thread UV_Unwrapping regarding to UV unwrapping in three.js . I want to make a 3D sculpting of the following 2D image -
I studied a little bit about photogrammetry but avoided SGBM algorithm (since it is compute intensive) and skipped to the last step - generating point cloud mesh from depth map. For depth map I graycycled the image and considered RGB values as depth. What I came up is like the following -
And my model is link is - model.zip (821.5 KB)
But I am facing problem with UV unwrapping. It looks like following -
How can I map the UV-coordinates properly ?
My code is the following -
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.CvType;
import org.opencv.core.Scalar;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import java.io.*;
import java.util.Scanner;
public class trilinear_inp{
public double round(double num){
int floor = (int) num;
double floor_d = (double) floor;
double celing_d = floor_d + 1;
double mid_d = (floor_d + celing_d)/2;
if(num < mid_d){
return floor_d;
}else if(num >= mid_d){
return celing_d;
}else{
System.out.println("Unable to round off");
return 0;
}
}
public Mat interpolate(Mat ip,int op_height,int op_width){
trilinear_inp ob = new trilinear_inp();
int ip_h = ip.rows();
int ip_w = ip.cols();
Mat op = new Mat(op_height,op_width,CvType.CV_8UC3);
for(int i=0;i<op_height;i++){
for(int j=0;j<op_width;j++){
double uf = ((double)i)/op_height*ip_h;
double vf = ((double)j)/op_width*ip_w;
int ui = (int) uf;
int vi = (int) vf;
int u2 = ui+1, v2 = vi+1;
double mu = uf - ui, nu = vf - vi;
if(ui < 0){
ui = 0;
}else if(ui >= 0 && ui < ip_h){
ui = ui;
}else if(ui >= ip_h){
ui = ip_h-1;
}else{
System.err.println("vi not found!");
}
if(u2 < 0){
u2 = 0;
}else if(u2 >= 0 && u2 < ip_h){
u2 = u2;
}else if(u2 >= ip_h){
u2 = ip_h-1;
}else{
System.err.println("v2 not found!");
}
double[] a = ip.get(ui,vi % ip_w);
double[] b = ip.get(ui,v2 % ip_w);
double[] c = ip.get(u2,vi % ip_w);
double[] d = ip.get(u2,v2 % ip_w);
double[] dd = new double[3];
dd[0] = a[0]*(1-mu)*(1-nu) + b[0]*mu*(1-nu) + c[0]*(1-mu)*nu + d[0]*mu*nu;
dd[1] = a[1]*(1-mu)*(1-nu) + b[1]*mu*(1-nu) + c[1]*(1-mu)*nu + d[1]*mu*nu;
dd[2] = a[2]*(1-mu)*(1-nu) + b[2]*mu*(1-nu) + c[2]*(1-mu)*nu + d[2]*mu*nu;
double[] dd_r = new double[]{ ob.round(dd[0]),ob.round(dd[1]),ob.round(dd[2]) };
try{
op.put(i,j,dd_r);
}catch(Exception e){}
}
}return op;
}
public double[] getNormal(double[] center,double[] h_coord,double[] v_coord){
double x1 = center[0], y1 = center[1], z1 = center[2], x2 = h_coord[0], y2 = h_coord[1], z2 = h_coord[2], x3 = v_coord[0], y3 = v_coord[1], z3 = v_coord[2];
double xf = (y2 - y1)*(z3 - z1) - (y3 - y1)*(z2 - z1);
double yf = (x2 - x1)*(z3 - z1) - (x3 - x1)*(z2 - z1);
double zf = (x2 - x1)*(y3 - y1) - (x3 - x1)*(y2 - y1);
double a = Math.sqrt(xf*xf + yf*yf + zf*zf);
xf = xf / a;
yf = yf / a;
zf = zf / a;
return new double[]{xf,yf,zf};
}
public static void main(String[] args) throws Exception{
trilinear_inp obj = new trilinear_inp();
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
//System.out.print("Enter the path of the image: ");
//String input = (new Scanner(System.in)).nextLine();
Mat ip = Imgcodecs.imread("./img062.jpg");
int ip_h = ip.rows();
int ip_w = ip.cols();
System.out.println("height: "+ip_h+" width: "+ip_w);
System.out.print("Enter output width (length along x-axis): ");
int op_width = (new Scanner(System.in)).nextInt();
System.out.print("Enter output height (length along z-axis): ");
int op_height = (new Scanner(System.in)).nextInt();
System.out.print("Enter output depth (length along y-axis): ");
double op_depth = (new Scanner(System.in)).nextDouble();
FileWriter writer = new FileWriter("final.obj");
writer.write("# sample obj file\no Sample\n");
writer.write("mtllib final.mtl\n");
Mat op = obj.interpolate(ip,op_height,op_width);
double[][][] vertices = new double[op_height][op_width][3];
String vtstr = "";
for(int i=0;i<op_height;i++){
for(int j=0;j<op_width;j++){
double[] color = op.get(i,j);
double g = (color[0]+color[1]+color[2]) / 3;
double z = ( g * ( (double)op_depth / 255 ) );
double y = (1 - 2*((double)i/(op_height - 1)))*((double)op_height/op_width);
double x = (2*((double)j/(op_width - 1)) - 1);
vertices[i][j][0] = x;
vertices[i][j][1] = y;
vertices[i][j][2] = z;
writer.write("v "+x+" "+y+" "+z+"\n");
double u = 1 - ((double)i)/(op_height - 1);
double v = ((double)j)/(op_width - 1);
vtstr += "vt "+y+" "+x+"\n";
}
}
writer.write(vtstr);
double[][][] vn = new double[op_height][op_width][3];
String str = "";int c = 1;
for(int i=0;i<op_height;i++){
for(int j=0;j<op_width;j++){
if(i<op_height - 1&&j<op_width - 1){
int index = i*op_width + j + 1;
int index1 = (i + 1)*op_width + j + 1;
int index2 = (i + 1)*op_width + (j + 1) + 1;
int index3 = i*op_width + (j + 1) + 1;
str += "f "+index+"/"+c+" "+index1+"/"+c+" "+index2+"/"+c+" "+index3+"/"+c+"\n";
}c++;
}
}
//System.out.println(c);
writer.write("usemtl Material\n");
writer.write(str);
//f 200 50000 49801 1
writer.close();
}
}
I wrote it in JAVA with openCV(I took width: 200 height: 250 depth: 0.4).I am satisfied with the mesh.I will edit it further on blender.
Please help me to obtain the proper UV coordinates.
Ref: Object (.obj) files
Additional question: Is it has anything to do with vertex normal ?