def paintParameterLine(parameterLine, width, height, img): #PAINTPARAMETERLINE Paint parameterized line # parameterLine: [n1,n2,n3,planeID,u1,u2], first 3 dims are normal # direction, 4th dim is the base plane ID for U (1=XY), 5-6th dims are U # of start and end point. # width, height: the size of output panorama, width = height x 2 # img: the image on which lines will be drawn. If no img, # img=zeros(height,width). lines = parameterLine if img is None: panoEdgeC = np.zeros([height, width]) else: img = np.double(img) panoEdgeC = imresize(img, [height, width]) if img.shape[2] == 3: pimg = PIL.Image.fromarray(np.uint8(panoEdgeC)) panoEdgeC = pimg.convert('L') panoEdgeC = np.array(panoEdgeC) * 0.5 # valid = true(size(lines,1),1); # uv_vp = xyz2vp([vp;-vp]); # vpm = min(floor( (uv_vp(:,1)-(-pi)) /(2*pi)*width)+1, width); # vpn = min(floor( ((pi/2)-uv_vp(:,2))/(pi)*height )+1, height); # valid = lines(:,4)==1; # lines = lines(~valid,:); #horizontal # lines = lines(valid,:); #vertical num_sample = max(height, width) for i in np.arange(lines.shape[0]): # fprintf('#d\n',i); n = lines[i, 0:3] sid = lines[i, 4] * 2 * np.pi eid = lines[i, 5] * 2 * np.pi if eid < sid: x = np.linspace(sid, eid + 2 * np.pi, num_sample) x = x % (2 * np.pi) # x = sid-1:(eid-1+numBins); # x = rem(x,numBins) + 1; else: x = np.linspace(sid, eid, num_sample) # u = -pi + (x'-1)*uBinSize + uBinSize/2; u = -np.pi + x.T v = CoordsTransform.computeUVN(n, u, lines[i, 3]) xyz = CoordsTransform.uv2xyzN(np.column_stack((u, v)), lines[i, 3]) uv = CoordsTransform.xyz2uvN(xyz, 0) uv = uv.T m = np.minimum(np.floor((uv[:, 0] - (-np.pi)) / (2 * np.pi) * width), width - 1) n = np.minimum(np.floor(((np.pi / 2) - uv[:, 1]) / (np.pi) * height), height - 1) #drawId = sub2ind([height, width], n, m); panoEdgeC[np.int32(n), np.int32(m)] = 255 return panoEdgeC
def rotatePanorama(img, vp, R): #ROTATEPANORAMA Rotate panorama # if R is given, vp (vanishing point) will be overlooked # otherwise R is computed from vp [sphereH, sphereW, C] = img.shape # rotImg = zeros( sphereH, sphereW, C); ## new uv coordinates [TX, TY] = np.meshgrid(np.arange(sphereW), np.arange(sphereH)) TX = TX.T.flatten() + 1 TY = TY.T.flatten() + 1 ANGx = (TX - sphereW / 2 - 0.5) / sphereW * np.pi * 2 ANGy = -(TY - sphereH / 2 - 0.5) / sphereH * np.pi uvNew = np.column_stack((ANGx, ANGy)) xyzNew = CoordsTransform.uv2xyzN(uvNew, 0) ## rotation matrix if R == None: R = np.dot(np.diag([1, 1, 1]), np.linalg.pinv(vp.T)) xyzOld = np.dot(np.linalg.pinv(R), xyzNew.T).T uvOld = CoordsTransform.xyz2uvN(xyzOld, 0).T # Px = uvOld(:,1)/2/pi*sphereW + 0.5 + sphereW/2; # Py = -uvOld(:,2)/pi*sphereH + 0.5 + sphereH/2; Px = (uvOld[:, 0] + np.pi) / (2 * np.pi) * sphereW + 0.5 Py = (-uvOld[:, 1] + np.pi / 2) / np.pi * sphereH + 0.5 Px = np.reshape(Px, [sphereW, sphereH]).T Py = np.reshape(Py, [sphereW, sphereH]).T # boundary imgNew = np.double(np.zeros([sphereH + 2, sphereW + 2, C])) imgNew[1:-1, 1:-1, :] = img imgNew[1:-1, 0, :] = img[:, -1, :] imgNew[1:-1, -1, :] = img[:, 0, :] halfW = np.int(sphereW / 2) imgNew[0, 1:halfW + 1, :] = img[0, sphereW:halfW - 1:-1, :] imgNew[0, halfW + 1:-1, :] = img[0, halfW - 1::-1, :] imgNew[-1, 1:halfW + 1, :] = img[-1, sphereW:halfW - 1:-1, :] imgNew[-1, halfW + 1:-1, :] = img[0, halfW:0:-1, :] imgNew[0, 0, :] = img[0, 0, :] imgNew[-1, -1, :] = img[-1, -1, :] imgNew[0, -1, :] = img[0, -1, :] imgNew[-1, 0, :] = img[-1, 0, :] rotImg = Projection.warpImageFast(imgNew, Px + 1, Py + 1) # rotImg = warpImageFast(img, Px, Py); return rotImg, R
def assignVanishingType(lines, vp, tol, area): #ASSIGNVANISHINGTYPE Summary of this function goes here # Detailed explanation goes here if area < 0: area = 10 numLine = lines.shape[0] numVP = vp.shape[0] typeCost = np.zeros([numLine, numVP]) # perpendicular for vid in np.arange(numVP): cosint = np.sum(lines[:, 0:3] * repmat(vp[vid, :], numLine, 1), 1) typeCost[:, vid] = np.arcsin(np.abs(cosint)) # infinity for vid in np.arange(numVP): valid = np.ones([numLine, 1], dtype=bool) for i in np.arange(numLine): us = lines[i, 4] ue = lines[i, 5] u = np.array([us, ue]) * 2.0 * np.pi - np.pi v = CoordsTransform.computeUVN(lines[i, 0:3], u, lines[i, 3]) xyz = CoordsTransform.uv2xyzN(np.row_stack((u, v)).T, lines[i, 3]) x = np.linspace(xyz[0, 0], xyz[1, 0], 100) y = np.linspace(xyz[0, 1], xyz[1, 1], 100) z = np.linspace(xyz[0, 2], xyz[1, 2], 100) xyz = np.column_stack((x, y, z)) xyz = xyz / repmat(np.sqrt(np.sum(xyz**2, 1)), 3, 1).T ang = np.arccos(np.abs(np.sum(xyz * repmat(vp[vid, :], 100, 1), 1))) valid[i] = not any(ang < area * np.pi / 180) typeCost[~valid[:, 0], vid] = 100 I = np.min(typeCost, 1) type = np.argmin(typeCost, 1) type[I > tol] = numVP return [type, typeCost]
def rotateLines(lines, R): #ROTATELINES Rotate lines on panorama # lines: parameterized lines, R: rotation matrix [numLine, dimLine] = lines.shape lines_N = np.zeros([numLine, dimLine]) for i in np.arange(numLine): n = lines[i, 0:3] sid = lines[i, 4] * 2 * np.pi - np.pi eid = lines[i, 5] * 2 * np.pi - np.pi u = np.row_stack((sid, eid)) v = CoordsTransform.computeUVN(n, u, lines[i, 3]) xyz = CoordsTransform.uv2xyzN(np.column_stack((u, v)), lines[i, 3]) n_N = np.dot(R, n.T).T n_N = n_N / np.linalg.norm(n_N, 2) xyz_N = np.dot(R, xyz.T).T lines_N[i, 3] = np.argmax(np.abs(n_N[[2, 0, 1]])) uv_N = CoordsTransform.xyz2uvN(xyz_N, lines_N[i, 3]).T umax = max(uv_N[:, 0]) + np.pi umin = min(uv_N[:, 0]) + np.pi if umax - umin > np.pi: lines_N[i, 4:6] = np.array([umax, umin]) / 2 / np.pi else: lines_N[i, 4:6] = np.array([umin, umax]) / 2 / np.pi lines_N[i, 0:3] = n_N # lines_N(i,5:6) = (uv_N(:,1)'+pi)/2/pi; if dimLine >= 7: lines_N[i, 6] = np.arccos( np.sum(xyz_N[0, :] * xyz_N[1, :]) / (np.linalg.norm(xyz_N[0, :], 2) * np.linalg.norm(xyz_N[1, :], 2))) # lines_N(i,7) = lines(i,7); # this should be ok as well if dimLine >= 8: lines_N[i, 7] = lines[i, 7] return lines_N
def refitLineSegmentB(lines, vp, vpweight): #REFITLINESEGMENTA refit direction of line segments # lines: original line segments # vp: vannishing point # vpweight: if set to 0, lines will not change; if set to inf, lines will # be forced to pass vp if vpweight == None: vpweight = 0.1 numSample = 100 numLine = lines.shape[0] xyz = np.zeros([numSample + 1, 3]) wei = np.ones([numSample + 1, 1]) wei[numSample] = vpweight * numSample lines_ali = lines for i in np.arange(numLine): n = lines[i, 0:3] sid = lines[i, 4] * 2 * np.pi eid = lines[i, 5] * 2 * np.pi if eid < sid: x = np.linspace(sid, eid + 2 * np.pi, numSample) x = (x % (2 * np.pi)) # x = sid-1:(eid-1+numBins); # x = rem(x,numBins) + 1; else: x = np.linspace(sid, eid, numSample) # u = -pi + (x'-1)*uBinSize + uBinSize/2; u = -np.pi + x.T v = CoordsTransform.computeUVN(n, u, lines[i, 3]) xyz[0:numSample, :] = CoordsTransform.uv2xyzN(np.column_stack((u, v)), lines[i, 3]) xyz[numSample, :] = vp _, outputNM = curveFitting(xyz, wei) lines_ali[i, 0:3] = outputNM return lines_ali
def gbPanoSegment(img, sigma, k, minSz): #GBPANOSEGMENT Graph-based image segmentation on panorama # Similar as Pedro's algorithm, only the graph is built on sphere, so # left and right side are considered as attached. # img: should be in uint8 [0~256] # sigma, k, minSz: same parameters as in Pedro's algorithm [height, width, _] = img.shape #img_smooth = smooth(img, sigma); #sigma = 10; img_smooth = np.zeros([height, width, 3]) img_smooth[:, :, 0] = gaussian_filter(img[:, :, 0], sigma) img_smooth[:, :, 1] = gaussian_filter(img[:, :, 1], sigma) img_smooth[:, :, 2] = gaussian_filter(img[:, :, 2], sigma) #SrcImage = './data/rotImg_smooth.mat' #dict = loadmat(SrcImage) #img_smooth = dict['img_smooth'] #plt.subplot(2, 1, 1) #plt.imshow(np.uint8(img)) #plt.subplot(2, 1, 2) #plt.imshow(np.uint8(img_smooth)) #plt.show() ## uniformly sample vectors on sphere and segment, test later dict = loadmat('./data/uniformvector_lvl8.mat') coor = dict['coor'] tri = dict['tri'] #[coor, tri] = getUniformVector(8); # [ E ] = getSketchTokenEdgemap( img ); # [EE, Ix, Iy] = dt2(double(E), 0.1, 0, 0.1, 0 ); EE = np.zeros([height, width]) xySubs = CoordsTransform.uv2coords(CoordsTransform.xyz2uvN(coor, 0), width, height, 0) xySubs = np.int32(xySubs) #SrcImage = './data/xySubs.mat' #dict = loadmat(SrcImage) #xySubs = dict['xySubs'] #xySubs = xySubs -1; idx = np.where(xySubs[:, 1] < 0) xySubs[idx, 1] = 0 idx = np.where(xySubs[:, 1] >= 512) xySubs[idx, 1] = 511 idx = np.where(xySubs[:, 0] >= 1024) xySubs[idx, 0] = 1023 SubXY = np.array([xySubs[:, 1], xySubs[:, 0]]).T #xyinds = np.ravel_multi_index(SubXY,(height ,width)); #offset = width*height; tri = tri - 1 e0 = np.array([tri[:, 0], tri[:, 1]]).T e1 = np.array([tri[:, 1], tri[:, 2]]).T e2 = np.array([tri[:, 2], tri[:, 0]]).T edges = np.row_stack((e0, e1, e2)) invert = edges[:, 1] < edges[:, 0] edges[invert, :] = edges[invert, 1::-1] uniEdges, _ = np.unique(edges, return_inverse=True, axis=0) #eid0 = np.unravel_index(xyinds[uniEdges[:,0]],(height,width,3)) #eid1 = np.unravel_index(xyinds[uniEdges[:,1]],(height,width,3)) eid0 = SubXY[uniEdges[:, 0], :].T eid1 = SubXY[uniEdges[:, 1], :].T #eid0offset = np.unravel_index(xyinds[uniEdges[:,0]] + offset,(height,width,3)) #eid1offset = np.unravel_index(xyinds[uniEdges[:,1]] + offset,(height,width,3)) #eid0offset2 = np.unravel_index(xyinds[uniEdges[:,0]] + 2 * offset,(height,width,3)) #eid1offset2 = np.unravel_index(xyinds[uniEdges[:,1]] + 2 * offset,(height,width,3)) if any(eid0[:, 0] >= 512): print('nono') weight = (img_smooth[eid0[0], eid0[1], 0] - img_smooth[eid1[0], eid1[1], 0] )**2 + (img_smooth[eid0[0], eid0[1], 1] - img_smooth[eid1[0], eid1[1], 1])**2 + ( img_smooth[eid0[0], eid0[1], 2] - img_smooth[eid1[0], eid1[1], 2])**2 gdweight = (EE[eid0[0], eid0[1]] + EE[eid0[0], eid0[1]]) / 2 panoEdge = np.array([ uniEdges[:, 0], uniEdges[:, 1], np.sqrt(np.double(weight)) + 10 * np.double(gdweight) ]) maxID = coor.shape[0] num = uniEdges.shape[0] edgeLabel = segmentGraphEdge((maxID, num, panoEdge, k, minSz)) L = np.unique(edgeLabel) temp = np.zeros(len(edgeLabel)) [gridX, gridY] = np.meshgrid(np.arange(width), np.arange(height)) for i in np.arange(len(L)): temp[edgeLabel == L[i]] = i + 1 pixelvector = CoordsTransform.uv2xyzN( CoordsTransform.coords2uv([gridX[:] + 1, gridY[:] + 1], width, height), 0) # k = 1; # [nnidx, dists] = annsearch( coor', pixelvector', k); #[nnidx, dists] = knnsearch( coor, pixelvector); nbrs = NearestNeighbors(n_neighbors=1, algorithm='auto').fit(coor) dists, nnidx = nbrs.kneighbors(pixelvector) #from scipy import spatial #tree = spatial.KDTree(coor); #dists, nnidx = tree.query(pixelvector,k=1); #SrcImage = './data/temp.mat' #dict = loadmat(SrcImage) #tempm = dict['temp'] #SrcImage = './data/nnidx.mat' #dict = loadmat(SrcImage) #nnidxm = dict['nnidx'] #nnidxm = nnidxm - 1 panoSegment = np.reshape(temp[nnidx], [width, height]).T #pimg = PIL.Image.fromarray(np.uint8(panoSegment)) ##pimggray = pimg.convert('L') #pimg.save('./data/segmentation.jpg'); return panoSegment
def combineEdgesN(edges): #COMBINEEDGES Combine some small line segments, should be very conservative # lines: combined line segments # ori_lines: original line segments # line format: [nx ny nz projectPlaneID umin umax LSfov score] arcList = [] for i in np.arange(edges.shape[0]): panoLst = edges[i].panoLst if panoLst[0].shape[0] == 0: continue if (len(arcList)) == 0: arcList = panoLst else: arcList = np.row_stack((arcList, panoLst)) ## ori lines numLine = arcList.shape[0] ori_lines = np.zeros((numLine, 8)) areaXY = np.abs( np.sum(arcList[:, 0:3] * repmat([0, 0, 1], arcList.shape[0], 1), 1)) areaYZ = np.abs( np.sum(arcList[:, 0:3] * repmat([1, 0, 0], arcList.shape[0], 1), 1)) areaZX = np.abs( np.sum(arcList[:, 0:3] * repmat([0, 1, 0], arcList.shape[0], 1), 1)) vec = [areaXY, areaYZ, areaZX] #[_, planeIDs] = np.max(vec, 1); # 1:XY 2:YZ 3:ZX planeIDs = np.argmax(vec, 0) for i in np.arange(numLine): ori_lines[i, 0:3] = arcList[i, 0:3] ori_lines[i, 3] = planeIDs[i] coord1 = arcList[i, 3:6] coord2 = arcList[i, 6:9] uv = CoordsTransform.xyz2uvN(np.row_stack((coord1, coord2)), planeIDs[i]) umax = np.max(uv[0, :]) + np.pi umin = np.min(uv[0, :]) + np.pi if umax - umin > np.pi: ori_lines[i, 4:6] = np.column_stack((umax, umin)) / 2 / np.pi # ori_lines(i,7) = umin + 1 - umax; else: ori_lines[i, 4:6] = np.column_stack((umin, umax)) / 2 / np.pi # ori_lines(i,7) = umax - umin; ori_lines[i, 6] = np.arccos( np.sum(coord1 * coord2) / (np.linalg.norm(coord1, 2) * np.linalg.norm(coord2, 2))) ori_lines[i, 7] = arcList[i, 9] # valid = ori_lines(:,3)<0; # ori_lines(valid,1:3) = -ori_lines(valid,1:3); ## additive combination lines = ori_lines # panoEdge = paintParameterLine( lines, 1024, 512); # figure; imshow(panoEdge); for iter in np.arange(3): numLine = lines.shape[0] valid_line = np.ones([numLine], dtype=bool) for i in np.arange(numLine): # fprintf('#d/#d\n', i, numLine); if valid_line[i] == False: continue dotProd = np.sum(lines[:, 0:3] * repmat(lines[i, 0:3], numLine, 1), 1) valid_curr = (np.abs(dotProd) > np.cos( 1 * np.pi / 180)) & valid_line valid_curr[i] = False valid_ang = np.where(valid_curr) for j in valid_ang[0]: range1 = lines[i, 4:6] range2 = lines[j, 4:6] valid_rag = intersection(range1, range2) if valid_rag == False: continue # combine I = np.argmax(np.abs(lines[i, 0:3])) if lines[i, I] * lines[j, I] > 0: nc = lines[i, 0:3] * lines[i, 6] + lines[j, 0:3] * lines[j, 6] else: nc = lines[i, 0:3] * lines[i, 6] - lines[j, 0:3] * lines[j, 6] nc = nc / np.linalg.norm(nc, 2) if insideRange(range1[0], range2): nrmin = range2[0] else: nrmin = range1[0] if insideRange(range1[1], range2): nrmax = range2[1] else: nrmax = range1[1] u = np.array([nrmin, nrmax]) * 2 * np.pi - np.pi v = CoordsTransform.computeUVN(nc, u, lines[i, 3]) xyz = CoordsTransform.uv2xyzN(np.column_stack((u, v)), lines[i, 3]) length = np.arccos(np.sum(xyz[0, :] * xyz[1, :])) scr = (lines[i, 6] * lines[i, 7] + lines[j, 6] * lines[j, 7]) / (lines[i, 6] + lines[j, 6]) nc = np.append(nc, lines[i, 3]) nc = np.append(nc, nrmin) nc = np.append(nc, nrmax) nc = np.append(nc, length) nc = np.append(nc, scr) newLine = nc lines[i, :] = newLine valid_line[j] = False lines = lines[valid_line, :] print('iter: #d, before: #d, after: #d\n', iter, len(valid_line), sum(valid_line)) return [lines, ori_lines] '''