900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 6目摄像头照片球面投影变换拼接全景图片

6目摄像头照片球面投影变换拼接全景图片

时间:2022-07-23 13:06:20

相关推荐

6目摄像头照片球面投影变换拼接全景图片

最近在做全景拼接项目,有有六张来自于六目摄像头的图片,分别来自不同方向上的图片,摄像头示意图如下:

各方向上图片的位置示意图如下:

假设相对应位置的图片为拼接起来后(此处我们用代码进行了拼接,而且需要这样结构拼接起来作为输入):

球面变换和拼接的代码如下:

from PIL import Imageimport mathimport numpy as npimport cv2def spherical_coordinates(i, j, w, h):""" Returns spherical coordinates of the pixel from the output image. """theta = 2*float(i)/float(w)-1phi = 2*float(j)/float(h)-1# phi = lat, theta = longreturn phi*(math.pi/2), theta*math.pidef vector_coordinates(phi, theta):""" Returns 3D vector which points to the pixel location inside a sphere. """return (math.cos(phi) * math.cos(theta), # Xmath.sin(phi),# Ymath.cos(phi) * math.sin(theta)) # Z# Assign identifiers to the faces of the cubeFACE_Z_POS = 1 # LeftFACE_Z_NEG = 2 # RightFACE_Y_POS = 3 # TopFACE_Y_NEG = 4 # BottomFACE_X_NEG = 5 # FrontFACE_X_POS = 6 # Backdef get_face(x, y, z):""" Uses 3D vector to find which cube face the pixel lies on. """largest_magnitude = max(abs(x), abs(y), abs(z))if largest_magnitude - abs(x) < 0.00001:return FACE_X_POS if x < 0 else FACE_X_NEGelif largest_magnitude - abs(y) < 0.00001:return FACE_Y_POS if y < 0 else FACE_Y_NEGelif largest_magnitude - abs(z) < 0.00001:return FACE_Z_POS if z < 0 else FACE_Z_NEGdef raw_face_coordinates(face, x, y, z):"""Return coordinates with necessary sign (- or +) depending on which face they lie on.From Open-GL specification (chapter 3.8.10) /registry/doc/glspec41.core.0725.pdf"""if face == FACE_X_NEG:xc = zyc = yma = xreturn xc, yc, maelif face == FACE_X_POS:xc = -zyc = yma = xreturn xc, yc, maelif face == FACE_Y_NEG:xc = zyc = -xma = yreturn xc, yc, maelif face == FACE_Y_POS:xc = zyc = xma = yreturn xc, yc, maelif face == FACE_Z_POS:xc = xyc = yma = zreturn xc, yc, maelif face == FACE_Z_NEG:xc = -xyc = yma = zreturn xc, yc, madef raw_coordinates(xc, yc, ma):""" Return 2D coordinates on the specified face relative to the bottom-left corner of the face. Also from Open-GL spec."""return (float(xc)/abs(float(ma)) + 1) / 2, (float(yc)/abs(float(ma)) + 1) / 2def face_origin_coordinates(face, n):""" Return bottom-left coordinate of specified face in the input image. """if face == FACE_X_NEG:return n, nelif face == FACE_X_POS:return 3*n, nelif face == FACE_Z_NEG:return 2*n, nelif face == FACE_Z_POS:return 0, nelif face == FACE_Y_POS:return n, 0elif face == FACE_Y_NEG:return n, 2*ndef normalized_coordinates(face, x, y, n):""" Return pixel coordinates in the input image where the specified pixel lies. """face_coords = face_origin_coordinates(face, n)normalized_x = math.floor(x*n)normalized_y = math.floor(y*n)# Stop out of bound behaviourif normalized_x < 0:normalized_x = 0elif normalized_x >= n:normalized_x = n-1if normalized_y < 0:normalized_x = 0elif normalized_y >= n:normalized_y = n-1return face_coords[0] + normalized_x, face_coords[1] + normalized_ydef find_corresponding_pixel(i, j, w, h, n):""":param i: X coordinate of output image pixel:param j: Y coordinate of output image pixel:param w: Width of output image:param h: Height of output image:param n: Height/Width of each square face:return: Pixel coordinates for the input image that a specified pixel in the output image maps to."""spherical = spherical_coordinates(i, j, w, h)vector_coords = vector_coordinates(spherical[0], spherical[1])face = get_face(vector_coords[0], vector_coords[1], vector_coords[2])raw_face_coords = raw_face_coordinates(face, vector_coords[0], vector_coords[1], vector_coords[2])cube_coords = raw_coordinates(raw_face_coords[0], raw_face_coords[1], raw_face_coords[2])return normalized_coordinates(face, cube_coords[0], cube_coords[1], n)def get_six_pics_stitching(val_resize):size_t = val_resize# generate a (512,512) black imagetarget = np.zeros((size_t, size_t), dtype=np.uint8) ret = cv2.cvtColor(target, cv2.COLOR_GRAY2BGR)imgs_index = ["top", "left", "front", "right", "back", "down"]imgs_set = []# read all the images from target filefor i in range(6):img = cv2.imread("./pics/{}.jpg".format(imgs_index[i]))img_res = cv2.resize(img, (size_t, size_t))imgs_set.append(img_res)# first row stitchingret_pano1 = np.concatenate((ret, imgs_set[0]), axis=1)for i in range(2):ret_pano1 = np.concatenate((ret_pano1, ret), axis=1)# Second row stitchingimgs_mid_four = imgs_set[1:5]ret_pano2 = imgs_mid_four[0]for i in range(3):ret_pano2 = np.concatenate((ret_pano2, imgs_mid_four[i + 1]), axis=1)# Third row stitchingret_pano3 = np.concatenate((ret, imgs_set[5]), axis=1)for i in range(2):ret_pano3 = np.concatenate((ret_pano3, ret), axis=1)# whole image sitichingret_pano = np.concatenate((ret_pano1, ret_pano2), axis=0)ret_pano = np.concatenate((ret_pano, ret_pano3), axis=0)cv2.imwrite('six_pics_stitching.jpg',ret_pano)def convert_img(infile, outfile):inimg = Image.open(infile)wo, ho = inimg.size# Calculate height and width of output image, and size of each square faceh = int(wo/3)w = 2*hn = int(ho/3)# Create new image with width w, and height houtimg = Image.new('RGB', (w, h))# For each pixel in output image find colour value from input imagefor ycoord in range(0, h):for xcoord in range(0, w):corrx, corry = find_corresponding_pixel(xcoord, ycoord, w, h, n)outimg.putpixel((xcoord, ycoord), inimg.getpixel((corrx, corry)))# Print progress percentageprint(str(round((float(ycoord)/float(h))*100, 2)) + '%')outimg.save(outfile, 'PNG')if __name__ == '__main__':val_resize = 512# you need put your images in the file"./pics/" or you can define by yourself.get_six_pics_stitching(val_resize)convert_img('six_pics_stitching.jpg', 'output.jpg')# out_img = cv2.imread('output.jpg')# cv2.imshow('out_img', out_img)# cv2.waitKey()

拼接后的效果如图:

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。