展开菜单
首页 精品内容 本月促销 装机必备 Windows PDF教程 macOS软件 IOS软件 Android AI 专题
全部分类

当前位置:

首页 > 编程开发 > 基于Python实现单目三维重建的步骤与方法

基于Python实现单目三维重建的步骤与方法

一、单目三维重建概述客观世界的物体是三维的,而我们用摄像机获取的图像是二维的,但是我们可以通过二维图像感知目标的三维信息。三维重建技术是以一定的方式处理图像进而得到计算机能够识别的三维信息,由此对目标进行分析。而单目三维重建则是根据单个摄像头的运动来模拟双目视觉,从而获得物体在空间中的三维视觉信息,其中,单目即指单个摄像头。二、实现过程在对物体进行单目三维重建的过程中,相关运行环境如下:matplotlib3.3.4numpy1.19.5opencv-contrib-python3.4.2.16openc

本文目录

      一、单目三维重建概述

      客观世界的物体是三维的,而我们用摄像机获取的图像是二维的,但是我们可以通过二维图像感知目标的三维信息。三维重建技术是以一定的方式处理图像进而得到计算机能够识别的三维信息,由此对目标进行分析。而单目三维重建则是根据单个摄像头的运动来模拟双目视觉,从而获得物体在空间中的三维视觉信息,其中,单目即指单个摄像头。

      二、实现过程

      在对物体进行单目三维重建的过程中,相关运行环境如下:

      matplotlib 3.3.4
      numpy 1.19.5
      opencv-contrib-python 3.4.2.16
      opencv-python 3.4.2.16
      pillow 8.2.0
      python 3.6.2

      其重建主要包含以下步骤:

      (1)相机的标定

      (2)图像特征提取及匹配

      (3)三维重建

      接下来,我们来详细看下每个步骤的具体实现:

      (1)相机的标定

      在我们日常生活中有很多相机,如手机上的相机、数码相机及功能模块型相机等等,每一个相机的参数都是不同的,即相机拍出的照片的分辨率、模式等。假设我们在进行物体三维重建的时候,事先并不知道我们相机的矩阵参数,那么,我们就应当计算出相机的矩阵参数,这一个步骤就叫做相机的标定。相机标定的相关原理我就不介绍了,网上很多人都讲解的挺详细的。其标定的具体实现如下:

      def camera_calibration(ImagePath):
          # 循环中断
          criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
          # 棋盘格尺寸(棋盘格的交叉点的个数)
          row = 11
          column = 8
          
          objpoint = np.zeros((row * column, 3), np.float32)
          objpoint[:, :2] = np.mgrid[0:row, 0:column].T.reshape(-1, 2)
      
          objpoints = []  # 3d point in real world space
          imgpoints = []  # 2d points in image plane.
      
          batch_images = glob.glob(ImagePath + '/*.jpg')
          for i, fname in enumerate(batch_images):
              img = cv2.imread(batch_images[i])
              imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
              # find chess board corners
              ret, corners = cv2.findChessboardCorners(imgGray, (row, column), None)
              # if found, add object points, image points (after refining them)
              if ret:
                  objpoints.append(objpoint)
                  corners2 = cv2.cornerSubPix(imgGray, corners, (11, 11), (-1, -1), criteria)
                  imgpoints.append(corners2)
                  # Draw and display the corners
                  img = cv2.drawChessboardCorners(img, (row, column), corners2, ret)
                  cv2.imwrite('Checkerboard_Image/Temp_JPG/Temp_' + str(i) + '.jpg', img)
      
          print("成功提取:", len(batch_images), "张图片角点!")
          ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, imgGray.shape[::-1], None, None)

      其中,cv2.calibrateCamera函数求出的mtx矩阵即为K矩阵。

      当修改好相应参数并完成标定后,我们可以输出棋盘格的角点图片来看看是否已成功提取棋盘格的角点,输出角点图如下:

      基于Python实现单目三维重建的步骤与方法

      图1:棋盘格角点提取

      (2)图像特征提取及匹配

      在整个三维重建的过程中,这一步是最为关键的,也是最为复杂的一步,图片特征提取的好坏决定了你最后的重建效果。
      在图片特征点提取算法中,有三种算法较为常用,分别为:SIFT算法、SURF算法以及ORB算法。通过综合分析对比,我们在这一步中采取SURF算法来对图片的特征点进行提取。三种算法的特征点提取效果对比如果大家感兴趣可以去网上搜来看下,在此就不逐一对比了。具体实现如下:

      def epipolar_geometric(Images_Path, K):
          IMG = glob.glob(Images_Path)
          img1, img2 = cv2.imread(IMG[0]), cv2.imread(IMG[1])
          img1_gray = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
          img2_gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
      
          # Initiate SURF detector
          SURF = cv2.xfeatures2d_SURF.create()
      
          # compute keypoint & descriptions
          keypoint1, descriptor1 = SURF.detectAndCompute(img1_gray, None)
          keypoint2, descriptor2 = SURF.detectAndCompute(img2_gray, None)
          print("角点数量:", len(keypoint1), len(keypoint2))
      
          # Find point matches
          bf = cv2.BFMatcher(cv2.NORM_L2, crossCheck=True)
          matches = bf.match(descriptor1, descriptor2)
          print("匹配点数量:", len(matches))
      
          src_pts = np.asarray([keypoint1[m.queryIdx].pt for m in matches])
          dst_pts = np.asarray([keypoint2[m.trainIdx].pt for m in matches])
          # plot
          knn_image = cv2.drawMatches(img1_gray, keypoint1, img2_gray, keypoint2, matches[:-1], None, flags=2)
          image_ = Image.fromarray(np.uint8(knn_image))
          image_.save("MatchesImage.jpg")
      
          # Constrain matches to fit homography
          retval, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 100.0)
      
          # We select only inlier points
          points1 = src_pts[mask.ravel() == 1]
          points2 = dst_pts[mask.ravel() == 1]

      找到的特征点如下:

      基于Python实现单目三维重建的步骤与方法

      图2:特征点提取

      (3)三维重建

      我们找到图片的特征点并相互匹配后,则可以开始进行三维重建了,具体实现如下:

      points1 = cart2hom(points1.T)
      points2 = cart2hom(points2.T)
      # plot
      fig, ax = plt.subplots(1, 2)
      ax[0].autoscale_view('tight')
      ax[0].imshow(cv2.cvtColor(img1, cv2.COLOR_BGR2RGB))
      ax[0].plot(points1[0], points1[1], 'r.')
      ax[1].autoscale_view('tight')
      ax[1].imshow(cv2.cvtColor(img2, cv2.COLOR_BGR2RGB))
      ax[1].plot(points2[0], points2[1], 'r.')
      plt.savefig('MatchesPoints.jpg')
      fig.show()
      # 
      
      points1n = np.dot(np.linalg.inv(K), points1)
      points2n = np.dot(np.linalg.inv(K), points2)
      E = compute_essential_normalized(points1n, points2n)
      print('Computed essential matrix:', (-E / E[0][1]))
      
      P1 = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0]])
      P2s = compute_P_from_essential(E)
      
      ind = -1
      for i, P2 in enumerate(P2s):
          # Find the correct camera parameters
          d1 = reconstruct_one_point(points1n[:, 0], points2n[:, 0], P1, P2)
          # Convert P2 from camera view to world view
          P2_homogenous = np.linalg.inv(np.vstack([P2, [0, 0, 0, 1]]))
          d2 = np.dot(P2_homogenous[:3, :4], d1)
          if d1[2] > 0 and d2[2] > 0:
              ind = i
      
      P2 = np.linalg.inv(np.vstack([P2s[ind], [0, 0, 0, 1]]))[:3, :4]
      Points3D = linear_triangulation(points1n, points2n, P1, P2)
      
      fig = plt.figure()
      fig.suptitle('3D reconstructed', fontsize=16)
      ax = fig.gca(projection='3d')
      ax.plot(Points3D[0], Points3D[1], Points3D[2], 'b.')
      ax.set_xlabel('x axis')
      ax.set_ylabel('y axis')
      ax.set_zlabel('z axis')
      ax.view_init(elev=135, azim=90)
      plt.savefig('Reconstruction.jpg')
      plt.show()

      其重建效果如下(效果一般):

      基于Python实现单目三维重建的步骤与方法

      图3:三维重建

      三、结论

      从重建的结果来看,单目三维重建效果一般,我认为可能与这几方面因素有关:

      (1)图片拍摄形式。如果是进行单目三维重建任务,在拍摄图片时最好保持平行移动相机,且最好正面拍摄,即不要斜着拍或特异角度进行拍摄;

      (2)拍摄时周边环境干扰。选取拍摄的地点最好保持单一,减少无关物体的干扰;

      (3)拍摄光源问题。选取的拍照场地要保证合适的亮度(具体情况要试才知道你们的光源是否达标),还有就是移动相机的时候也要保证前一时刻和此时刻的光源一致性。

      其实,单目三维重建的效果确实一般,就算将各方面情况都拉满,可能得到的重建效果也不是特别好。或者我们可以考虑采用双目三维重建,双目三维重建效果肯定是要比单目的效果好的,在实现是也就麻烦一(亿)点点,哈哈。其实也没有多太多的操作,主要就是整两个相机拍摄和标定两个相机麻烦点,其他的都还好。

      四、代码

      import cv2
      import json
      import numpy as np
      import glob
      from PIL import Image
      import matplotlib.pyplot as plt
      plt.rcParams['font.sans-serif'] = ['SimHei']
      plt.rcParams['axes.unicode_minus'] = False
      
      
      def cart2hom(arr):
          """ Convert catesian to homogenous points by appending a row of 1s
          :param arr: array of shape (num_dimension x num_points)
          :returns: array of shape ((num_dimension+1) x num_points) 
          """
          if arr.ndim == 1:
              return np.hstack([arr, 1])
          return np.asarray(np.vstack([arr, np.ones(arr.shape[1])]))
      
      
      def compute_P_from_essential(E):
          """ Compute the second camera matrix (assuming P1 = [I 0])
              from an essential matrix. E = [t]R
          :returns: list of 4 possible camera matrices.
          """
          U, S, V = np.linalg.svd(E)
      
          # Ensure rotation matrix are right-handed with positive determinant
          if np.linalg.det(np.dot(U, V)) < 0:
              V = -V
      
          # create 4 possible camera matrices (Hartley p 258)
          W = np.array([[0, -1, 0], [1, 0, 0], [0, 0, 1]])
          P2s = [np.vstack((np.dot(U, np.dot(W, V)).T, U[:, 2])).T,
                 np.vstack((np.dot(U, np.dot(W, V)).T, -U[:, 2])).T,
                 np.vstack((np.dot(U, np.dot(W.T, V)).T, U[:, 2])).T,
                 np.vstack((np.dot(U, np.dot(W.T, V)).T, -U[:, 2])).T]
      
          return P2s
      
      
      def correspondence_matrix(p1, p2):
          p1x, p1y = p1[:2]
          p2x, p2y = p2[:2]
      
          return np.array([
              p1x * p2x, p1x * p2y, p1x,
              p1y * p2x, p1y * p2y, p1y,
              p2x, p2y, np.ones(len(p1x))
          ]).T
      
          return np.array([
              p2x * p1x, p2x * p1y, p2x,
              p2y * p1x, p2y * p1y, p2y,
              p1x, p1y, np.ones(len(p1x))
          ]).T
      
      
      def scale_and_translate_points(points):
          """ Scale and translate image points so that centroid of the points
              are at the origin and avg distance to the origin is equal to sqrt(2).
          :param points: array of homogenous point (3 x n)
          :returns: array of same input shape and its normalization matrix
          """
          x = points[0]
          y = points[1]
          center = points.mean(axis=1)  # mean of each row
          cx = x - center[0]  # center the points
          cy = y - center[1]
          dist = np.sqrt(np.power(cx, 2) + np.power(cy, 2))
          scale = np.sqrt(2) / dist.mean()
          norm3d = np.array([
              [scale, 0, -scale * center[0]],
              [0, scale, -scale * center[1]],
              [0, 0, 1]
          ])
      
          return np.dot(norm3d, points), norm3d
      
      
      def compute_image_to_image_matrix(x1, x2, compute_essential=False):
          """ Compute the fundamental or essential matrix from corresponding points
              (x1, x2 3*n arrays) using the 8 point algorithm.
              Each row in the A matrix below is constructed as
              [x'*x, x'*y, x', y'*x, y'*y, y', x, y, 1]
          """
          A = correspondence_matrix(x1, x2)
          # compute linear least square solution
          U, S, V = np.linalg.svd(A)
          F = V[-1].reshape(3, 3)
      
          # constrain F. Make rank 2 by zeroing out last singular value
          U, S, V = np.linalg.svd(F)
          S[-1] = 0
          if compute_essential:
              S = [1, 1, 0]  # Force rank 2 and equal eigenvalues
          F = np.dot(U, np.dot(np.diag(S), V))
      
          return F
      
      
      def compute_normalized_image_to_image_matrix(p1, p2, compute_essential=False):
          """ Computes the fundamental or essential matrix from corresponding points
              using the normalized 8 point algorithm.
          :input p1, p2: corresponding points with shape 3 x n
          :returns: fundamental or essential matrix with shape 3 x 3
          """
          n = p1.shape[1]
          if p2.shape[1] != n:
              raise ValueError('Number of points do not match.')
      
          # preprocess image coordinates
          p1n, T1 = scale_and_translate_points(p1)
          p2n, T2 = scale_and_translate_points(p2)
      
          # compute F or E with the coordinates
          F = compute_image_to_image_matrix(p1n, p2n, compute_essential)
      
          # reverse preprocessing of coordinates
          # We know that P1' E P2 = 0
          F = np.dot(T1.T, np.dot(F, T2))
      
          return F / F[2, 2]
      
      
      def compute_fundamental_normalized(p1, p2):
          return compute_normalized_image_to_image_matrix(p1, p2)
      
      
      def compute_essential_normalized(p1, p2):
          return compute_normalized_image_to_image_matrix(p1, p2, compute_essential=True)
      
      
      def skew(x):
          """ Create a skew symmetric matrix *A* from a 3d vector *x*.
              Property: np.cross(A, v) == np.dot(x, v)
          :param x: 3d vector
          :returns: 3 x 3 skew symmetric matrix from *x*
          """
          return np.array([
              [0, -x[2], x[1]],
              [x[2], 0, -x[0]],
              [-x[1], x[0], 0]
          ])
      
      
      def reconstruct_one_point(pt1, pt2, m1, m2):
          """
              pt1 and m1 * X are parallel and cross product = 0
              pt1 x m1 * X  =  pt2 x m2 * X  =  0
          """
          A = np.vstack([
              np.dot(skew(pt1), m1),
              np.dot(skew(pt2), m2)
          ])
          U, S, V = np.linalg.svd(A)
          P = np.ravel(V[-1, :4])
      
          return P / P[3]
      
      
      def linear_triangulation(p1, p2, m1, m2):
          """
          Linear triangulation (Hartley ch 12.2 pg 312) to find the 3D point X
          where p1 = m1 * X and p2 = m2 * X. Solve AX = 0.
          :param p1, p2: 2D points in homo. or catesian coordinates. Shape (3 x n)
          :param m1, m2: Camera matrices associated with p1 and p2. Shape (3 x 4)
          :returns: 4 x n homogenous 3d triangulated points
          """
          num_points = p1.shape[1]
          res = np.ones((4, num_points))
      
          for i in range(num_points):
              A = np.asarray([
                  (p1[0, i] * m1[2, :] - m1[0, :]),
                  (p1[1, i] * m1[2, :] - m1[1, :]),
                  (p2[0, i] * m2[2, :] - m2[0, :]),
                  (p2[1, i] * m2[2, :] - m2[1, :])
              ])
      
              _, _, V = np.linalg.svd(A)
              X = V[-1, :4]
              res[:, i] = X / X[3]
      
          return res
      
      
      def writetofile(dict, path):
          for index, item in enumerate(dict):
              dict[item] = np.array(dict[item])
              dict[item] = dict[item].tolist()
          js = json.dumps(dict)
          with open(path, 'w') as f:
              f.write(js)
              print("参数已成功保存到文件")
      
      
      def readfromfile(path):
          with open(path, 'r') as f:
              js = f.read()
              mydict = json.loads(js)
          print("参数读取成功")
          return mydict
      
      
      def camera_calibration(SaveParamPath, ImagePath):
          # 循环中断
          criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
          # 棋盘格尺寸
          row = 11
          column = 8
          objpoint = np.zeros((row * column, 3), np.float32)
          objpoint[:, :2] = np.mgrid[0:row, 0:column].T.reshape(-1, 2)
      
          objpoints = []  # 3d point in real world space
          imgpoints = []  # 2d points in image plane.
          batch_images = glob.glob(ImagePath + '/*.jpg')
          for i, fname in enumerate(batch_images):
              img = cv2.imread(batch_images[i])
              imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
              # find chess board corners
              ret, corners = cv2.findChessboardCorners(imgGray, (row, column), None)
              # if found, add object points, image points (after refining them)
              if ret:
                  objpoints.append(objpoint)
                  corners2 = cv2.cornerSubPix(imgGray, corners, (11, 11), (-1, -1), criteria)
                  imgpoints.append(corners2)
                  # Draw and display the corners
                  img = cv2.drawChessboardCorners(img, (row, column), corners2, ret)
                  cv2.imwrite('Checkerboard_Image/Temp_JPG/Temp_' + str(i) + '.jpg', img)
          print("成功提取:", len(batch_images), "张图片角点!")
          ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, imgGray.shape[::-1], None, None)
          dict = {'ret': ret, 'mtx': mtx, 'dist': dist, 'rvecs': rvecs, 'tvecs': tvecs}
          writetofile(dict, SaveParamPath)
      
          meanError = 0
          for i in range(len(objpoints)):
              imgpoints2, _ = cv2.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist)
              error = cv2.norm(imgpoints[i], imgpoints2, cv2.NORM_L2) / len(imgpoints2)
              meanError += error
          print("total error: ", meanError / len(objpoints))
      
      
      def epipolar_geometric(Images_Path, K):
          IMG = glob.glob(Images_Path)
          img1, img2 = cv2.imread(IMG[0]), cv2.imread(IMG[1])
          img1_gray = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
          img2_gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
      
          # Initiate SURF detector
          SURF = cv2.xfeatures2d_SURF.create()
      
          # compute keypoint & descriptions
          keypoint1, descriptor1 = SURF.detectAndCompute(img1_gray, None)
          keypoint2, descriptor2 = SURF.detectAndCompute(img2_gray, None)
          print("角点数量:", len(keypoint1), len(keypoint2))
      
          # Find point matches
          bf = cv2.BFMatcher(cv2.NORM_L2, crossCheck=True)
          matches = bf.match(descriptor1, descriptor2)
          print("匹配点数量:", len(matches))
      
          src_pts = np.asarray([keypoint1[m.queryIdx].pt for m in matches])
          dst_pts = np.asarray([keypoint2[m.trainIdx].pt for m in matches])
          # plot
          knn_image = cv2.drawMatches(img1_gray, keypoint1, img2_gray, keypoint2, matches[:-1], None, flags=2)
          image_ = Image.fromarray(np.uint8(knn_image))
          image_.save("MatchesImage.jpg")
      
          # Constrain matches to fit homography
          retval, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 100.0)
      
          # We select only inlier points
          points1 = src_pts[mask.ravel() == 1]
          points2 = dst_pts[mask.ravel() == 1]
      
          points1 = cart2hom(points1.T)
          points2 = cart2hom(points2.T)
          # plot
          fig, ax = plt.subplots(1, 2)
          ax[0].autoscale_view('tight')
          ax[0].imshow(cv2.cvtColor(img1, cv2.COLOR_BGR2RGB))
          ax[0].plot(points1[0], points1[1], 'r.')
          ax[1].autoscale_view('tight')
          ax[1].imshow(cv2.cvtColor(img2, cv2.COLOR_BGR2RGB))
          ax[1].plot(points2[0], points2[1], 'r.')
          plt.savefig('MatchesPoints.jpg')
          fig.show()
          # 
      
          points1n = np.dot(np.linalg.inv(K), points1)
          points2n = np.dot(np.linalg.inv(K), points2)
          E = compute_essential_normalized(points1n, points2n)
          print('Computed essential matrix:', (-E / E[0][1]))
      
          P1 = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0]])
          P2s = compute_P_from_essential(E)
      
          ind = -1
          for i, P2 in enumerate(P2s):
              # Find the correct camera parameters
              d1 = reconstruct_one_point(points1n[:, 0], points2n[:, 0], P1, P2)
              # Convert P2 from camera view to world view
              P2_homogenous = np.linalg.inv(np.vstack([P2, [0, 0, 0, 1]]))
              d2 = np.dot(P2_homogenous[:3, :4], d1)
              if d1[2] > 0 and d2[2] > 0:
                  ind = i
      
          P2 = np.linalg.inv(np.vstack([P2s[ind], [0, 0, 0, 1]]))[:3, :4]
          Points3D = linear_triangulation(points1n, points2n, P1, P2)
      
          return Points3D
      
      
      def main():
          CameraParam_Path = 'CameraParam.txt'
          CheckerboardImage_Path = 'Checkerboard_Image'
          Images_Path = 'SubstitutionCalibration_Image/*.jpg'
      
          # 计算相机参数
          camera_calibration(CameraParam_Path, CheckerboardImage_Path)
          # 读取相机参数
          config = readfromfile(CameraParam_Path)
          K = np.array(config['mtx'])
          # 计算3D点
          Points3D = epipolar_geometric(Images_Path, K)
          # 重建3D点
          fig = plt.figure()
          fig.suptitle('3D reconstructed', fontsize=16)
          ax = fig.gca(projection='3d')
          ax.plot(Points3D[0], Points3D[1], Points3D[2], 'b.')
          ax.set_xlabel('x axis')
          ax.set_ylabel('y axis')
          ax.set_zlabel('z axis')
          ax.view_init(elev=135, azim=90)
          plt.savefig('Reconstruction.jpg')
          plt.show()
      
      
      if __name__ == '__main__':
          main()
      本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
      作者最新文章
      编程开发 Python
      相关文章 更多
      精品专题 更多
      装机必备

      正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

      Windows

      正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

      PDF教程

      正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

      macOS软件

      正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

      IOS软件

      正软商城iOS软件专区,精选适用于iPhone和iPad的办公、学习、影音、设计、效率及AI应用,提供功能介绍、适用设备、系统要求和正版获取方式等信息。

      AI

      正软商城AI软件专区,汇集AI写作、AI绘画、AI视频、AI办公、AI编程、AI翻译、智能客服和数据分析等人工智能工具,提供功能介绍、适用平台、收费方式及正版购买信息。

      Mac软件 更多
      Aperty macOS版
      Aperty macOS版

      Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

      火山引擎 网页版
      火山引擎 网页版

      火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

      立刻MV 网页版
      立刻MV 网页版

      立刻MV 面向音乐人、内容创作者和品牌团队,帮助用户低成本完成歌曲 MV、歌词视频、AI 分镜、图生视频与最终合成。

      蛙蛙写作 网页版
      蛙蛙写作 网页版

      蛙蛙写作 AI 创作工具,覆盖小说、剧本、文案,一键生成文稿,打通文字转视频全流程,高效解决创作难题。

      讯飞智作 网页版
      讯飞智作 网页版

      讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

      超级简历WonderCV 网页版
      超级简历WonderCV 网页版

      超级简历WonderCV是面向应届生和AI小白的智能求职平台,覆盖简历、面试与职业规划。

      音述AI 网页版
      音述AI 网页版

      音述AI,是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区。

      AionClaw macOS版
      AionClaw macOS版

      AionClaw 是可在桌面端运行的任务型 AI 助手,通过数字专家与技能市场组合办公、创作、数据和开发能力。

      Loomy macOS版
      Loomy macOS版

      Loomy 是科大讯飞推出的桌面 AI 助手,可通过对话、任务与工作目录协助处理办公、内容创作和资料整理。

      AirBuddy 3 macOS版
      AirBuddy 3 macOS版

      AirBuddy 3 是面向 macOS 的蓝牙外设增强工具,可集中查看 AirPods、Beats 与苹果设备电量,提供快速连接、播放控制、电量提醒、桌面小组件和多台 Mac 外设接力等功能。

      AirServer macOS版
      AirServer macOS版

      AirServer macOS版可把 Mac 转换为无线投屏接收端,通过 AirPlay 或 Google Cast 接收手机、平板和电脑画面,并支持多设备同时连接、高清镜像及会话录制,适合家庭娱乐、课堂教学、会议演示和应用展示。

      AnyDesk macOS版
      AnyDesk macOS版

      AnyDesk macOS版是一款适用于远程办公、设备维护和客户支持的远程桌面工具,可连接并操作异地计算机,支持文件传输、无人值守访问、会话权限控制及跨平台协作。

      WINDOWS 更多
      讯飞绘文 网页版
      讯飞绘文 网页版

      讯飞绘文网页版是科大讯飞推出的AI图文创作与内容运营工具,覆盖热点选题、文章生成、稿件校对、智能配图、排版发布和数据复盘等环节,适合自媒体创作者及内容团队在线使用。

      Maya(Autodesk Maya) Windows版
      Maya(Autodesk Maya) Windows版

      Autodesk Maya 是面向影视、电视、动画和游戏行业的专业三维制作软件,集多边形与 NURBS 建模、角色绑定、关键帧和动作捕捉动画、Bifrost 特效模拟、材质开发及 Arnold 渲染于一体,

      Aperty Windows版
      Aperty Windows版

      Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

      火山引擎 网页版
      火山引擎 网页版

      火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

      立刻MV 网页版
      立刻MV 网页版

      立刻MV 面向音乐人、内容创作者和品牌团队,帮助用户低成本完成歌曲 MV、歌词视频、AI 分镜、图生视频与最终合成。

      蛙蛙写作 网页版
      蛙蛙写作 网页版

      蛙蛙写作 AI 创作工具,覆盖小说、剧本、文案,一键生成文稿,打通文字转视频全流程,高效解决创作难题。

      讯飞智作 网页版
      讯飞智作 网页版

      讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

      超级简历WonderCV 网页版
      超级简历WonderCV 网页版

      超级简历WonderCV是面向应届生和AI小白的智能求职平台,覆盖简历、面试与职业规划。

      音述AI 网页版
      音述AI 网页版

      音述AI,是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区。

      AionClaw Windows版
      AionClaw Windows版

      AionClaw 是可在桌面端运行的任务型 AI 助手,通过数字专家与技能市场组合办公、创作、数据和开发能力。

      Loomy Windows版
      Loomy Windows版

      Loomy 是科大讯飞推出的桌面 AI 助手,可通过对话、任务与工作目录协助处理办公、内容创作和资料整理。

      AirServer Windows版
      AirServer Windows版

      AirServer Windows版可把电脑变成AirPlay、Google Cast和Miracast无线投屏接收端,适合会议演示、课堂教学及家庭大屏分享。发送设备通常无需另装客户端,并可同时接收和智能排列多个镜像会话。