Exemple #1
0
def estimate_rotation_matrices(chunk, i, j):
    groups = copy.copy(chunk.camera_groups)

    groups.append(None)
    for group in groups:
        group_cameras = list(filter(lambda c: c.group == group, chunk.cameras))

        if len(group_cameras) == 0:
            continue

        if len(group_cameras) == 1:
            if group_cameras[0].reference.rotation is None:
                group_cameras[0].reference.rotation = ps.Vector([0, 0, 0])
            continue

        for idx, c in enumerate(group_cameras[0:-1]):
            next_camera = group_cameras[idx + 1]

            if c.reference.rotation is None:
                if c.reference.location is None or next_camera.reference.location is None:
                    continue
                direction = delta_vector_to_chunk(
                    c.reference.location, next_camera.reference.location)

                cos_yaw = direction * j
                yaw = math.degrees(
                    math.acos(cos_yaw)) + 90  # TODO not sure about this offset

                if direction * i > 0:
                    yaw = -yaw

                c.reference.rotation = ps.Vector([yaw, 0, 0])

        group_cameras[-1].reference.rotation = group_cameras[
            -2].reference.rotation
 def setup_camera(self):
     # Imported camera coordinates projection
     self.chunk.crs = self.WGS_84
     # Accuracy for camera position in m
     self.chunk.camera_location_accuracy = PhotoScan.Vector([1, 1, 1])
     # Accuracy for camera orientations in degree
     self.chunk.camera_rotation_accuracy = PhotoScan.Vector([1, 1, 1])
Exemple #3
0
    def getSVGObject(self):
        photo = I3_Photo()
        photo.add_point(p1)
        photo.add_point(p2)
        photo.label = "test_Label"
        p_bottom_left = PhotoScan.Vector((0, 2000))
        p_bottom_right = PhotoScan.Vector((2000, 2000))
        p_upper_left = PhotoScan.Vector((0, 0))
        p_upper_right = PhotoScan.Vector((2000, 0))
        photo.add_point(I3_Point(measurement_I=p_bottom_left, projection_I=p_bottom_left))
        photo.add_point(I3_Point(measurement_I=p_bottom_right, projection_I=PhotoScan.Vector((2001, 2001))))
        photo.add_point(I3_Point(measurement_I=p_upper_left, projection_I=p_upper_left))
        photo.add_point(I3_Point(measurement_I=p_upper_right, projection_I=p_upper_right))

        class psSensor():
            height = 2000
            width = 2000

        class psCamera():
            sensor = psSensor()

        cam_dummy = psCamera()

        photo.photoScan_camera = cam_dummy
        return SVG_Photo_Representation([photo], 700)
Exemple #4
0
    def getPhotoforRasterTest(cls):
        photo = I3_Photo()
        photo.add_point(p1)
        photo.add_point(p2)
        photo.label = "test_Label"
        p_bottom_left = PhotoScan.Vector((0, 2000))
        p_bottom_right = PhotoScan.Vector((2000, 2000))
        p_upper_left = PhotoScan.Vector((0, 0))
        p_upper_right = PhotoScan.Vector((2000, 0))
        photo.add_point(I3_Point(measurement_I=p_bottom_left, projection_I=PhotoScan.Vector((-1, 2001))))
        photo.add_point(I3_Point(measurement_I=p_bottom_right, projection_I=PhotoScan.Vector((2001, 2001))))
        photo.add_point(I3_Point(measurement_I=p_upper_left, projection_I=PhotoScan.Vector((-1, -1))))
        photo.add_point(I3_Point(measurement_I=p_upper_right, projection_I=PhotoScan.Vector((2001, -1))))

        class psSensor():
            height = 2000
            width = 1990

        class psCamera():
            sensor = psSensor()

        cam_dummy = psCamera()

        photo.photoScan_camera = cam_dummy
        return photo
Exemple #5
0
def project_features(camera, points, features):
    """
    Project feature values from 3D points onto an image using the camera matrix.
    Requires PhotoScan library.

    Returns:
        projected_features - an array of (image_height, image_width, nfeatures) of feature
                             values corresponding to pixels in the image
    """

    import PhotoScan

    image_height = int(camera.meta['File/ImageHeight'])
    image_width = int(camera.meta['File/ImageWidth'])
    _, nfeatures = features.shape
    projected_features = np.zeros_like((image_height, image_width))

    for i, P in enumerate(points):
        P = PhotoScan.Vector(tuple(P))
        x, y = camera.project(P)
        x_in_image = x >= 0 and x < image_width
        y_in_image = y >= 0 and y < image_height
        if x_in_image and y_in_image:
            projected_features[y, x] = features[i]

    return projected_features.reshape((image_height, image_width, nfeatures))
Exemple #6
0
    def reset_view(self, magnification=80):
        doc.chunk = self.chunk
        chunk = self.chunk
        T = chunk.transform.matrix
        viewpoint = PhotoScan.app.viewpoint
        cx = viewpoint.width
        cy = viewpoint.height

        region = chunk.region
        r_center = region.center
        r_rotate = region.rot
        r_size = region.size
        r_vert = list()

        for i in range(8):  # bounding box corners
            r_vert.append(
                PhotoScan.Vector([
                    0.5 * r_size[0] * ((i & 2) - 1),
                    r_size[1] * ((i & 1) - 0.5),
                    0.25 * r_size[2] * ((i & 4) - 2)
                ]))
            r_vert[i] = r_center + r_rotate * r_vert[i]

        height = T.mulv(r_vert[1] - r_vert[0]).norm()
        width = T.mulv(r_vert[2] - r_vert[0]).norm()

        if width / cx > height / cy:
            scale = cx / width
        else:
            scale = cy / height

        PhotoScan.app.viewpoint.coo = T.mulp(chunk.region.center)
        PhotoScan.app.viewpoint.mag = magnification
Exemple #7
0
def bbox_to_cs():
    print("Script started...")

    doc = PhotoScan.app.document
    chunk = doc.chunk

    T = chunk.transform.matrix

    v_t = T.mulp(PhotoScan.Vector([0, 0, 0]))

    if chunk.crs:
        m = chunk.crs.localframe(v_t)
    else:
        m = PhotoScan.Matrix().Diag([1, 1, 1, 1])

    m = m * T
    s = math.sqrt(m[0, 0] ** 2 + m[0, 1] ** 2 + m[0, 2] ** 2)  # scale factor # s = m.scale()
    R = PhotoScan.Matrix([[m[0, 0], m[0, 1], m[0, 2]],
                          [m[1, 0], m[1, 1], m[1, 2]],
                          [m[2, 0], m[2, 1], m[2, 2]]])
    # R = m.rotation()

    R = R * (1. / s)

    reg = chunk.region
    reg.rot = R.t()
    chunk.region = reg

    print("Script finished!")
Exemple #8
0
class TestMyProject(unittest.TestCase):
    pho1 = I3_Photo()
    pho1.sigma_I = PhotoScan.Vector((2, 13))

    pho2 = I3_Photo()
    pho2.sigma_I = PhotoScan.Vector((5, 11))

    project = I3_Project()
    project.photos = [pho1, pho2]

    def test_calcGlobalSigma(self):
        rms_x, rms_y = self.project._get_RMS_4_all_photos()
        self.assertAlmostEqual(rms_x, 3.807886553, 6)
        self.assertAlmostEqual(rms_y, 12.04159458, 6)

    def test_createProjectSVG(self):
        pass
def photoscan_alignphotos(images, reference_eo, sequence):
    start_time = time.time()

    doc = PhotoScan.app.document
    chunk = doc.addChunk()
    chunk.addPhotos(images)
    for i in range(len(chunk.cameras)):
        chunk.cameras[i].reference.location = (float(reference_eo[6 * i]), float(reference_eo[6 * i + 1]), float(reference_eo[6 * i + 2]))
        chunk.cameras[i].reference.rotation = (float(reference_eo[6 * i + 5]), float(reference_eo[6 * i + 4]), float(reference_eo[6 * i + 3]))

    chunk.camera_location_accuracy = PhotoScan.Vector([0.001, 0.001, 0.001])
    chunk.camera_rotation_accuracy = PhotoScan.Vector([0.01, 0.01, 0.01])
    # chunk.cameras[-1].reference.location_accuracy = PhotoScan.Vector([10, 10, 10])
    # chunk.cameras[-1].reference.rotation_accuracy = PhotoScan.Vector([10, 10, 10])
    chunk.cameras[-1].reference.accuracy = PhotoScan.Vector([10, 10, 10])
    chunk.cameras[-1].reference.accuracy_ypr = PhotoScan.Vector([10, 10, 10])

    chunk.matchPhotos(accuracy=PhotoScan.MediumAccuracy)
    chunk.alignCameras()

    # doc.save("test_" + str(int(sequence)+1) + ".psz")

    camera = chunk.cameras[-1]
    if not camera.transform:
        print("There is no transformation matrix")

    estimated_coord = chunk.crs.project(
        chunk.transform.matrix.mulp(camera.center))  # estimated XYZ in coordinate system units
    T = chunk.transform.matrix
    m = chunk.crs.localframe(
        T.mulp(camera.center))  # transformation matrix to the LSE coordinates in the given point
    R = (m * T * camera.transform * PhotoScan.Matrix().Diag([1, -1, -1, 1])).rotation()
    estimated_ypr = PhotoScan.utils.mat2ypr(R)  # estimated orientation angles - yaw, pitch, roll
    estimated_opk = PhotoScan.utils.mat2opk(R)  # estimated orientation angles - omega, phi, kappa

    print(estimated_coord[0])
    print(estimated_coord[1])
    print(estimated_coord[2])
    print(estimated_ypr[0])
    print(estimated_ypr[1])
    print(estimated_ypr[2])
    print(estimated_opk[0])
    print(estimated_opk[1])
    print(estimated_opk[2])
Exemple #10
0
def get_photos_delta(chunk):
    mid_idx = int(len(chunk.cameras) / 2)
    if mid_idx == 0:
        return ps.Vector([0, 0, 0])
    c1 = chunk.cameras[:mid_idx][-1]
    c2 = chunk.cameras[:mid_idx][-2]
    offset = c1.reference.location - c2.reference.location
    for i in range(len(offset)):
        offset[i] = math.fabs(offset[i])
    return offset
Exemple #11
0
def dbg_test1():
    point2d = PhotoScan.Vector([1448, 1186])
    sensor = camera.sensor
    calibration = sensor.calibration
    p_x = camera.transform.mulp(sensor.calibration.unproject(point2d))
    print('p_x', p_x)
    print('camera center', camera.center)
    X = chunk.dense_cloud.pickPoint(camera.center, p_x)
    print('X', X)
    chunk.addMarker(point=X)
Exemple #12
0
def get_chunk_vectors(lat, lon):
    z = delta_vector_to_chunk(ps.Vector([lon, lat, 0]),
                              ps.Vector([lon, lat, 1]))
    y = delta_vector_to_chunk(ps.Vector([lon, lat, 0]),
                              ps.Vector([lon + 0.001, lat, 0]))
    x = delta_vector_to_chunk(ps.Vector([lon, lat, 0]),
                              ps.Vector([lon, lat + 0.001, 0]))
    return x, y, -z
Exemple #13
0
    def test_createSVG(self):
        photo = I3_Photo()
        photo.add_point(p1)
        photo.add_point(p2)
        photo.label = "test_Label"
        p_bottom_left = PhotoScan.Vector((0, 2000))
        p_bottom_right = PhotoScan.Vector((2000, 2000))
        p_upper_left = PhotoScan.Vector((0, 0))
        p_upper_right = PhotoScan.Vector((2000, 0))
        photo.add_point(I3_Point(measurement_I=p_bottom_left, projection_I=p_bottom_left))
        photo.add_point(I3_Point(measurement_I=p_bottom_right, projection_I=PhotoScan.Vector((2001, 0))))
        photo.add_point(I3_Point(measurement_I=p_upper_left, projection_I=p_upper_left))
        photo.add_point(I3_Point(measurement_I=p_upper_right, projection_I=p_upper_right))

        class psSensor():
            height = 2000
            width = 2000

        class psCamera():
            sensor = psSensor()

        cam_dummy = psCamera()

        photo.photoScan_camera = cam_dummy
Exemple #14
0
def build_mesh(output_file, min_latitude, max_latitude, min_longitude,
               max_longitude, lat_step, long_step):
    hgts_folder = get_hgts_folder()
    downloader_tasks = ['convert']
    downloader = hgt_downloader.HGTDownloader(min_latitude, min_longitude,
                                              max_latitude, max_longitude,
                                              hgts_folder, downloader_tasks)
    if not run_downloader(downloader):
        return

    def get_height(x, y):
        return downloader.elevation_data.get_elevation(x, y, approximate=True)

    mesh_points = np.array([
        [longitude, latitude,
         get_height(latitude, longitude)]
        for latitude in util.frange(min_latitude, max_latitude, lat_step)
        for longitude in util.frange(min_longitude, max_longitude, long_step)
    ])
    last_ok = 0
    for p in mesh_points:
        if p[2] is None:
            p[2] = last_ok
        else:
            last_ok = p[2]

    points = [ps.Vector(p) for p in mesh_points]
    faces = np.array(computeDelaunayTriangulation(points))
    norms = np.zeros(mesh_points.shape, dtype=mesh_points.dtype)

    tris = mesh_points[faces]
    # normals for all triangles
    n = np.cross(tris[::, 1] - tris[::, 0], tris[::, 2] - tris[::, 0])
    normalize_v3(n)
    norms[faces[:, 0]] += n
    norms[faces[:, 1]] += n
    norms[faces[:, 2]] += n
    normalize_v3(norms)

    with open(output_file, "w") as f:
        write_model_file(f, mesh_points, norms, faces)
    print("Successfully built mesh")

    ps.app.document.chunk.importModel(output_file)
    print("Mesh imported")
Exemple #15
0
def center_bbox_xyz():
    """Centers bounding box to XYZ center."""
    chunk = PhotoScan.app.document.chunk
    transform_matrix = chunk.transform.matrix
    if chunk.crs:
        vect_tm = transform_matrix * PhotoScan.Vector([0, 0, 0, 1])
        vect_tm.size = 3
        locfrm = chunk.crs.localframe(vect_tm)
    else:
        locfrm = PhotoScan.Matrix().diag([1, 1, 1, 1])
    locfrm = locfrm * transform_matrix
    sqrt = math.sqrt(locfrm[0, 0]**2 + locfrm[0, 1]**2 + locfrm[0, 2]**2)
    mat = PhotoScan.Matrix([[locfrm[0, 0], locfrm[0, 1], locfrm[0, 2]],
                            [locfrm[1, 0], locfrm[1, 1], locfrm[1, 2]],
                            [locfrm[2, 0], locfrm[2, 1], locfrm[2, 2]]])
    mat = mat * (1. / sqrt)
    reg = chunk.region
    reg.rot = mat.t()
    chunk.region = reg
Exemple #16
0
def align_cameras(chunk, min_latitude, min_longitude):
    if chunk.transform.scale is None:
        chunk.transform.scale = 1
        chunk.transform.rotation = ps.Matrix([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
        chunk.transform.translation = ps.Vector([0, 0, 0])

    i, j, k = get_chunk_vectors(min_latitude, min_longitude)  # i || North
    estimate_rotation_matrices(chunk, i, j)

    for c in chunk.cameras:
        if c.transform is not None:
            continue

        location = c.reference.location
        if location is None:
            continue
        chunk_coordinates = wgs_to_chunk(chunk, location)
        fi = c.reference.rotation.x + 90
        fi = math.radians(fi)
        roll = math.radians(c.reference.rotation.z)
        pitch = math.radians(c.reference.rotation.y)

        roll_mat = ps.Matrix([[1, 0, 0], [0,
                                          math.cos(roll), -math.sin(roll)],
                              [0, math.sin(roll),
                               math.cos(roll)]])
        pitch_mat = ps.Matrix([[math.cos(pitch), 0,
                                math.sin(pitch)], [0, 1, 0],
                               [-math.sin(pitch), 0,
                                math.cos(pitch)]])
        yaw_mat = ps.Matrix([[math.cos(fi), -math.sin(fi), 0],
                             [math.sin(fi), math.cos(fi), 0], [0, 0, 1]])

        r = roll_mat * pitch_mat * yaw_mat

        ii = r[0, 0] * i + r[1, 0] * j + r[2, 0] * k
        jj = r[0, 1] * i + r[1, 1] * j + r[2, 1] * k
        kk = r[0, 2] * i + r[1, 2] * j + r[2, 2] * k

        c.transform = ps.Matrix([[ii.x, jj.x, kk.x, chunk_coordinates[0]],
                                 [ii.y, jj.y, kk.y, chunk_coordinates[1]],
                                 [ii.z, jj.z, kk.z, chunk_coordinates[2]],
                                 [0, 0, 0, 1]])
Exemple #17
0
def cam_poly(cam_index, chunk):

    model = chunk.model
    faces = model.faces
    vertices = model.vertices
    camera = chunk.cameras[cam_index]

    sensor = camera.sensor
    steps = [(0, 0), (sensor.width - 1, 0),
             (sensor.width - 1, sensor.height - 1), (0, sensor.height - 1)]

    respoly = np.array([])
    for x, y in steps:
        point = PhotoScan.Vector([x, y])
        point = sensor.calibration.unproject(point)
        point = camera.transform.mulv(point)
        vect = point
        p = PhotoScan.Vector(camera.center)

        for face in faces:
            v = face.vertices
            E1 = PhotoScan.Vector(vertices[v[1]].coord - vertices[v[0]].coord)
            E2 = PhotoScan.Vector(vertices[v[2]].coord - vertices[v[0]].coord)
            D = PhotoScan.Vector(vect)
            T = PhotoScan.Vector(p - vertices[v[0]].coord)
            P = cross(D, E2)
            Q = cross(T, E1)
            result = PhotoScan.Vector([Q * E2, P * T, Q * D]) / (P * E1)

            if (0 < result[1]) and (0 < result[2]) and (result[1] + result[2]
                                                        <= 1):
                t = (1 - result[1] - result[2]) * vertices[v[0]].coord
                u = result[1] * vertices[v[1]].coord
                v_ = result[2] * vertices[v[2]].coord
                res = chunk.transform.matrix.mulp(u + v_ + t)
                res = chunk.crs.project(res)
                thisvert = np.r_[
                    res[0],
                    res[1]]  #(x,y) cordimates for a corner (defined in steps)
                break  #finish when the first intersection is found

        respoly = np.concatenate([thisvert, respoly])

    return (respoly)
Exemple #18
0
def add_altitude():
    """
    Adds user-defined altitude for camera instances in the Reference pane
    """

    doc = PhotoScan.app.document
    if not len(doc.chunks):
        raise Exception("No chunks!")

    alt = PhotoScan.app.getFloat("Please specify the height to be added:", 100)

    print("Script started...")
    chunk = doc.chunk

    for camera in chunk.cameras:
        if camera.reference.location:
            coord = camera.reference.location
            camera.reference.location = PhotoScan.Vector([coord.x, coord.y, coord.z + alt])

    print("Script finished!")
Exemple #19
0
def create_roi():
    """ Attempts to create the region ROI. This places the center of the ROI region """
    # """at the midpoint of all of the scale bar markers. """
    # """NOTE: This doesn't actually do anything yet."""
    x_axis, y_axis, z_axis = 0, 0, 0
    for chunk in PhotoScan.app.document.chunks:
        if chunk.label == 'Aligned Side A':
            x_axis, y_axis, z_axis = 0, 0, 0
            num_markers = chunk.markers.__len__()
            for marker in chunk.markers:
                x_axis += marker.position.x
                y_axis += marker.position.y
                z_axis += marker.position.z

            cent_x = x_axis / num_markers
            cent_y = y_axis / num_markers
            cent_z = z_axis / num_markers

            newregion = PhotoScan.Region()
            newregion.size = chunk.region.size
            newregion.rot = chunk.region.rot
            newregion.center = PhotoScan.Vector([cent_x, cent_y, cent_z])
            chunk.region = newregion
Exemple #20
0
def align_cameras(chunk, min_latitude, min_longitude):
    if chunk.transform.scale is None:
        chunk.transform.scale = 1
        chunk.transform.rotation = ps.Matrix([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
        chunk.transform.translation = ps.Vector([0, 0, 0])

    same_yaw_bound = 40  # within this bound all yaws are considered to be for same direction flights
    yaws_deltas, first_class_yaw = get_camera_calibration(chunk,
                                                          min_latitude,
                                                          min_longitude,
                                                          same_yaw_bound=40)

    print('Estimated yaw offsets {}'.format(yaws_deltas))

    i, j, k = get_chunk_vectors(min_latitude, min_longitude)  # i || North

    for c in chunk.cameras:
        group_index = chunk.camera_groups.index(
            c.group) if c.group is not None else -1

        location = c.reference.location
        if location is None:
            continue
        chunk_coordinates = wgs_to_chunk(chunk, location)
        fi = c.reference.rotation.x + 90
        idx = 0 if math.fabs(
            c.reference.rotation.x -
            first_class_yaw[group_index]) < same_yaw_bound else 1
        fi += yaws_deltas[group_index][idx]
        fi = math.radians(fi)

        ii, jj = i * math.cos(fi) + j * math.sin(fi), j * math.cos(
            fi) - i * math.sin(fi)
        c.transform = ps.Matrix([[ii.x, jj.x, k.x, chunk_coordinates[0]],
                                 [ii.y, jj.y, k.y, chunk_coordinates[1]],
                                 [ii.z, jj.z, k.z, chunk_coordinates[2]],
                                 [0, 0, 0, 1]])
marker_2D = (2000, 1000)  # projections of marker on the given photo

marker = chunk.addMarker()
marker.projections[camera] = marker_2D

point_2D = marker.projections[camera].coord
vect = camera.sensor.calibration.unproject(point_2D)
vect = camera.transform.mulv(vect)
center = camera.center

# estimating ray and surface intersection
for face in model.faces:

    v = face.vertices

    E1 = PhotoScan.Vector(vertices[v[1]].coord - vertices[v[0]].coord)
    E2 = PhotoScan.Vector(vertices[v[2]].coord - vertices[v[0]].coord)
    D = PhotoScan.Vector(vect)
    T = PhotoScan.Vector(center - vertices[v[0]].coord)
    P = cross(D, E2)
    Q = cross(T, E1)
    result = PhotoScan.Vector([Q * E2, P * T, Q * D]) / (P * E1)

    if (0 < result[1]) and (0 < result[2]) and (result[1] + result[2] <= 1):
        t = (1 - result[1] - result[2]) * vertices[v[0]].coord
        u = result[1] * vertices[v[1]].coord
        v_ = result[2] * vertices[v[2]].coord

        point_3D = T0.mulp(u + v_ + t)
        if chunk.crs:
            point_3D = chunk.crs.project(point_3D)
Exemple #22
0
def offsetsTest(document):

    chunk = document.chunk

    a_set = [1, 1.25, 1.5, 2, 2.5, 3, 3.5, 4, 5, 6, 7, 9, 11, 13, 15]
    zaccscale = [0.5, 1, 1.5, 2]
    xyacc = 0.03

    chunk.marker_projection_accuracy = 3

    x_list = []
    y_list = []
    z_list = []

    x_med = 0
    y_med = 0
    z_med = 0

    x_min = 100
    x_max = -100

    y_min = 100
    y_max = -100

    z_min = 100
    z_max = -100

    adj_r = 0
    adj_p = 0
    adj_y = 0

    f = 0

    meansq_x = 0
    meansq_y = 0
    meansq_z = 0

    pathCSV = document.path + "_offsets_test.csv"

    # accuracy
    # median x y z error min max
    # adj rpy
    #focal length

    with open(pathCSV, "w") as test:
        test.write(
            "t.p.acc z.acc x.med y.med z.med x.min y.min z.min x.max y.max z.max adj.r adj.p adj.y f meansqx meansqy meansqz \n"
        )

    #load markers
    path = os.path.dirname(PhotoScan.app.document.path)
    chunk.importMarkers(path + '/markers.xml')
    print("Markers path: " + path + '/markers.xml')

    for scale in zaccscale:
        z_acc = xyacc * scale
        chunk.camera_location_accuracy = PhotoScan.Vector(
            (float(xyacc), float(xyacc), float(z_acc)))
        for a in a_set:
            print(str(a) + ' ' + str(z_acc))
            #set parameters

            chunk.tiepoint_accuracy = a
            # uncheck markers
            #for m in chunk.markers:
            #m.reference.enabled = False
            chunk.remove(chunk.markers)

            #optimise
            chunk.optimizeCameras(fit_f=True,
                                  fit_cx=True,
                                  fit_cy=True,
                                  fit_b1=True,
                                  fit_b2=True,
                                  fit_k1=True,
                                  fit_k2=True,
                                  fit_k3=True,
                                  fit_k4=True,
                                  fit_p1=True,
                                  fit_p2=True,
                                  fit_p3=False,
                                  fit_p4=False)

            # check markers
            #for m in chunk.markers:
            #m.reference.enabled = True
            chunk.importMarkers(path + '/markers.xml')

            #export errors

            for m in chunk.markers:
                if len(m.projections.items()) > 2:
                    r = chunk.crs.unproject(m.reference.location)
                    e = chunk.transform.matrix.mulp(m.position)
                    l = chunk.crs.localframe(
                        chunk.transform.matrix.mulp(m.position))
                    v = l.mulv(e - r)
                    print("Errors: " + str(v[0]) + " " + str(v[1]) + " " +
                          str(v[2]) + " \n")
                    if (v[0] < x_min):
                        x_min = v[0]
                    if (v[0] > x_max):
                        x_max = v[0]
                    if (v[1] < y_min):
                        y_min = v[1]
                    if (v[1] > y_max):
                        y_max = v[1]
                    if (v[2] < z_min):
                        z_min = v[2]
                    if (v[2] > z_max):
                        z_max = v[2]

                    x_list.append(v[0])
                    y_list.append(v[1])
                    z_list.append(v[2])

            x_med = median(x_list)
            y_med = median(y_list)
            z_med = median(z_list)

            meansq_x = meansq(x_list)
            meansq_y = meansq(y_list)
            meansq_z = meansq(z_list)

            f = chunk.sensors[0].calibration.f

            with open(pathCSV, "a") as test:
                test.write(
                    str(a) + ' ' + str(z_acc) + ' ' + str(x_med) + ' ' +
                    str(y_med) + ' ' + str(z_med) + ' ' + str(x_min) + ' ' +
                    str(y_min) + ' ' + str(z_min) + ' ' + str(x_max) + ' ' +
                    str(y_max) + ' ' + str(z_max) + ' ' +
                    str(chunk.sensors[0].antenna.rotation[2]) + ' ' +
                    str(chunk.sensors[0].antenna.rotation[1]) + ' ' +
                    str(chunk.sensors[0].antenna.rotation[0]) + ' ' + str(f) +
                    ' ' + str(meansq_x) + ' ' + str(meansq_y) + ' ' +
                    str(meansq_z) + '\n')
Exemple #23
0
def processscan(scanfile):
    configfile = MonitorDirectory + scanfile
    log("JSON file: " + configfile)
    config = json.loads(open(configfile).read())
    scanid = config["scanid"]
    normaldir = config["normaldir"]
    projectdir = config["projectdir"]
    savedir = config["savedir"]

    try:
        SKETCHFAB_ENABLE = config["SKETCHFAB_ENABLE"]
        log("Taking JSON setting for sketchfab enable")
    except:
        log("Taking default sketchfab setting from main script")

    try:
        SKETCHFAB_DESCRIPTION = config["SKETCHFAB_DESCRIPTION"]
        log("Taking JSON setting for sketchfab description")
    except:
        log("Taking sketchfab description from main script")

# STEP 1 - Load Images
    doc = PhotoScan.app.document
    doc.clear()
    chunk = doc.addChunk()
    photos = os.listdir(normaldir)  # Get the photos filenames
    photos = [os.path.join(normaldir, p)
              for p in photos]  # Make them into a full path
    log("Found {} photos in {}".format(len(photos), normaldir))
    if not chunk.addPhotos(photos):
        log("ERROR: Failed to add photos: " + str(photos))

# STEP 2 - Detect Markers
    log("Dectecting markers on non-projected images")
    chunk.detectMarkers(PhotoScan.TargetType.CircularTarget12bit, 50)

    # STEP 3 - Create auto mask, if empty directory is specified in JSON file
    try:
        emptydir = config["emptydir"]
        log("Mask directory found, going to create auto mask")
    except:
        emptydir = ""
        log("No mask directory set, no auto making will take place")
    if (emptydir != ""):
        log("Creating auto mask based on non-projected images")
        maskpath = emptydir + "{filename}.jpg"
        chunk.importMasks(maskpath,
                          method='background',
                          tolerance=MaskTolerence)

# STEP 4 - Change images to projection images
    log("Switching to projection images")
    for i in range(len(chunk.cameras)):
        camera = chunk.cameras[i]
        photo = camera.photo.copy()
        photo.path = projectdir + camera.label
        camera.photo = photo

# STEP 5 - Align Images
    chunk.matchPhotos(accuracy=PhotoScan.HighAccuracy,
                      preselection=PhotoScan.NoPreselection,
                      filter_mask=True,
                      keypoint_limit=keypointLimit,
                      tiepoint_limit=tiepointLimit)
    chunk.alignCameras()

    # STEP 6 - Create Auto Bounding box
    mp0 = 0
    mpy = 0
    mpx = 0
    fp0 = 0
    fpy = 0
    fpx = 0
    #setting for Y up, Z forward -> needed for mixamo/unity
    vector0 = PhotoScan.Vector((0, 0, 0))
    vectorY = PhotoScan.Vector((0, 0, distancepy))  # Specify Y Distance
    vectorX = PhotoScan.Vector((distancepx, 0, 0))  # Specify X Distance
    c1 = 0
    c2 = 0
    c3 = 0
    c4 = 0
    c = 0

    for m in chunk.markers:
        if m.label == c1target:
            log("Center 1 point found")
            c1 = c
        if m.label == c2target:
            log("Center 2 point found")
            c2 = c
        if m.label == c3target:
            log("Center 3 point found")
            c3 = c
        if m.label == c4target:
            log("Center 4 point found")
            c4 = c
        if m.label == p0:
            mp0 = c
            fp0 = 1
            m.reference.location = vector0
            m.reference.enabled = 1
            log("Found floormat center point")
        if m.label == py:
            mpy = c
            fpy = 1
            m.reference.location = vectorY
            m.reference.enabled = 1
            log("found floormat Y point")
        if m.label == px:
            mpx = c
            fpx = 1
            m.reference.location = vectorX
            m.reference.enabled = 1
            log("found floormat X point")
        c = c + 1

    if fp0 and fpx and fpy:
        log("Found all markers")
        chunk.updateTransform()
    else:
        log("Error: not all markers found")

    newregion = chunk.region

    T = chunk.transform.matrix
    v_t = T * PhotoScan.Vector([0, 0, 0, 1])
    m = PhotoScan.Matrix().diag([1, 1, 1, 1])

    m = m * T
    s = math.sqrt(m[0, 0]**2 + m[0, 1]**2 + m[0, 2]**2)  #scale factor
    R = PhotoScan.Matrix([[m[0, 0], m[0, 1], m[0, 2]],
                          [m[1, 0], m[1, 1], m[1, 2]],
                          [m[2, 0], m[2, 1], m[2, 2]]])
    R = R * (1. / s)
    newregion.rot = R.t()

    # Calculate center point of the bounding box, by taking the average of 2 left and 2 right markers
    mx = (chunk.markers[c1].position + chunk.markers[c2].position +
          chunk.markers[c3].position + chunk.markers[c4].position) / 4

    mx = PhotoScan.Vector([mx[0], mx[1], mx[2]])
    newregion.center = mx

    dist = chunk.markers[mp0].position - chunk.markers[mpy].position
    dist = dist.norm()

    ratio = dist / distancepy

    newregion.size = PhotoScan.Vector(
        [boxwidth * ratio, boxheight * ratio, boxdepth * ratio])

    chunk.region = newregion
    chunk.updateTransform()

    log("Bounding box should be aligned now")

    # STEP 7 - Create Dense Cloud
    chunk.buildDenseCloud(quality=PhotoScan.HighQuality,
                          filter=PhotoScan.AggressiveFiltering)

    # STEP 8 - Create MESH
    chunk.buildModel(surface=PhotoScan.Arbitrary,
                     interpolation=PhotoScan.EnabledInterpolation,
                     face_count=PhotoScan.HighFaceCount)

    # STEP 9 - Switch projection images back to normal images
    for i in range(len(chunk.cameras)):
        camera = chunk.cameras[i]
        photo = camera.photo.copy()
        photo.path = normaldir + camera.label
        camera.photo = photo

    # STEP 10 - Do some basic clean up operations
    try:
        chunk.model.removeComponents(removecomponentsmax)
    except:
        log("Error Removing small components")
    try:
        chunk.model.fixTopology()
    except:
        log("Error Fix topology")
    try:
        chunk.model.closeHoles(100)
    except:
        log("Error closing holes")
    try:
        if smoothmodellevel > 1:
            chunk.smoothModel(smoothmodellevel)
    except:
        log("Error smoothing model")

    # STEP 11 - Create UVmap and Texture
    chunk.buildUV(mapping=PhotoScan.GenericMapping)
    chunk.buildTexture(blending=PhotoScan.MosaicBlending, size=8196)

    # STEP 12 - Save files
    doc.save(savedir + scanid + ".psz")
    modelpath = savedir + scanid + ".obj"
    chunk.exportModel(modelpath,
                      binary=True,
                      precision=6,
                      texture_format="jpg",
                      texture=True,
                      normals=True,
                      colors=True,
                      cameras=False,
                      format="obj")

    # STEP 13 - Zip files
    if SKETCHFAB_ENABLE:
        log("Zipping files to upload to sketchfab")
        zf = zipfile.ZipFile(savedir + scanid + ".zip", mode="w")
        try:
            zf.write(savedir + scanid + ".mtl")
            zf.write(savedir + scanid + ".obj")
            zf.write(savedir + scanid + ".jpg")
        finally:
            zf.close()
        zip_file = savedir + scanid + ".zip"

        # STEP 14 - Upload to sketchfab
        data = {
            'token': SKETCHFAB_API_TOKEN,
            'name': scanid,
            'description': SKETCHFAB_DESCRIPTION,
            'tags': SKETCHFAB_TAGS,
            'private': SKETCHFAB_PRIVATE,
            'password': SKETCHFAB_PASSWORD
        }

        f = open(zip_file, 'rb')
        files = {'modelFile': f}

        try:
            log("Uploading.. agisoft will pretend to hang while uploading, please wait"
                )
            PhotoScan.app.update()
            model_url = upload(data, files)
            sfile = open(savedir + scanid + "_sketchfabURL.txt", "w")
            sfile.write(model_url)
            sfile.close()
            log("Uploaded to Sketchfab")
        finally:
            f.close()

    log("=============================================================================="
        )
    log(" Completeted processing: " + scanid)
    log("=============================================================================="
        )
Exemple #24
0
def cross(a, b):
    result = PhotoScan.Vector(
        [a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x])
    return result
    logging.warning("Found no images in %s" % args.input)
    exit(-1)

logging.info("Adding %d images" % len(images))

chunk.addPhotos(images, PhotoScan.FlatLayout)

## Assign chunk to our station group
for c in chunk.cameras:
    c.group = group

    if center_paths and os.path.basename(c.photo.path) in center_paths:
        print("Found camera for center path at %s, fixing to the origin" %
              c.photo.path)

        c.reference.rotation = PhotoScan.Vector([0, 0, 0])
        c.reference.accuracy_ypr = PhotoScan.Vector([5, 5, 5])

chunk.matchPhotos(accuracy=PhotoScan.HighAccuracy,
                  generic_preselection=True,
                  reference_preselection=False)
chunk.alignCameras()

chunk.transform.rotation = PhotoScan.Utils.ypr2mat(
    PhotoScan.Vector([180, -20, 180]))

# for c in chunk.cameras:
#     print(c.transform)

# ## Find first aligned image
# first = next(c for c in chunk.cameras if c.transform)
Exemple #26
0
    def check_error(self):
        # Compatibility - Agisoft PhotoScan Professional 1.2.4
        # saves reprojection error for the tie points in the sparse cloud
        chunk = self.chunk
        M = chunk.transform.matrix
        point_cloud = chunk.point_cloud
        projections = point_cloud.projections
        points = point_cloud.points
        n_points = len(points)

        points_errors = {}
        error_list = []

        for photo in chunk.cameras:

            if not photo.transform:
                continue

            T = photo.transform.inv()
            calib = photo.sensor.calibration

            point_index = 0
            for proj in projections[photo]:
                track_id = proj.track_id
                while point_index < n_points and points[
                        point_index].track_id < track_id:
                    point_index += 1
                if point_index < n_points and points[
                        point_index].track_id == track_id:
                    if points[point_index].valid == False:
                        continue

                    coord = T * points[point_index].coord
                    coord.size = 3
                    dist = calib.error(coord, proj.coord).norm()**2
                    v = M * points[point_index].coord
                    v.size = 3

                    if point_index in points_errors.keys():
                        point_index = int(point_index)
                        points_errors[point_index].x += dist
                        points_errors[point_index].y += 1
                    else:
                        points_errors[point_index] = PhotoScan.Vector(
                            [dist, 1])

        for point_index in range(n_points):

            if points[point_index].valid is False:
                continue

            if chunk.crs:
                w = M * points[point_index].coord
                w.size = 3
                X, Y, Z = chunk.crs.project(w)
            else:
                X, Y, Z, w = M * points[point_index].coord

            error = math.sqrt(points_errors[point_index].x /
                              points_errors[point_index].y)
            error_list.append(error)
            error_list.sort()

        ave_error = sum(error_list) / len(
            error_list)  # for original photos, no point manipulation recorded

        valid_pt_list = []

        for pt in chunk.point_cloud.points:  # Makes a list of points that are NOT deleted
            if pt.valid is True:
                valid_pt_list.append(pt)
            else:
                continue

        count = 0

        print(ave_error)
        print(max(error_list))
        self.error = ave_error
        if self.start_error is None:
            self.start_error = ave_error
        return ave_error
Exemple #27
0
steps.extend(
    list(
        zip([camera.width - 1] * ((camera.height - 1) // step),
            list(range(0, camera.height - 1, step)))))
steps.extend(
    list(
        zip(list(range((camera.width - 1), 0, -step)),
            [camera.height - 1] * ((camera.width - 1) // step))))
steps.extend(
    list(
        zip([0] * ((camera.height - 1) // step),
            list(range(camera.height - 1, 0, -step)))))

for x, y in steps:

    point = PhotoScan.Vector([x, y])
    point = camera.calibration.unproject(point)
    point = camera.transform.mulv(point)
    vect = point
    p = PhotoScan.Vector(camera.center)

    for face in faces:

        v = face.vertices

        E1 = PhotoScan.Vector(vertices[v[1]].coord - vertices[v[0]].coord)
        E2 = PhotoScan.Vector(vertices[v[2]].coord - vertices[v[0]].coord)
        D = PhotoScan.Vector(vect)
        T = PhotoScan.Vector(p - vertices[v[0]].coord)
        P = cross(D, E2)
        Q = cross(T, E1)
Exemple #28
0
def get_shape_inf():

    chunk = PhotoScan.app.document.chunk
    region = chunk.region
    Mat = chunk.transform.matrix
    shapes = chunk.shapes

    chunk.optimizeCameras(fit_f=True,
                          fit_cx=True,
                          fit_cy=True,
                          fit_b1=True,
                          fit_b2=True,
                          fit_k1=True,
                          fit_k2=True,
                          fit_k3=True,
                          fit_k4=True,
                          fit_p1=True,
                          fit_p2=True,
                          fit_p3=True,
                          fit_p4=True)
    #optimize camera alignment
    chunk.matchPhotos(accuracy=PhotoScan.HighAccuracy,
                      generic_preselection=True,
                      reference_preselection=False)
    chunk.alignCameras()

    xmin = 10E+10
    ymin = 10E+10
    zmin = 10E+10
    xmax = -xmin
    ymax = -ymin
    zmax = -zmin
    padding = 1 + 0.05
    for shape in chunk.shapes:
        print(shape.vertices)
        #creates an array to hold all of the vertices for the shapes
        verts = [[] for _ in range(len(shape.vertices))]
        a = 0
        for v in shape.vertices:
            b = 3
            ver = [[] for _ in range(b)]
            ver = [[v.x], [v.y], [v.z]]

            if v.x > xmax:
                xmax = v.x
            if v.x < xmin:
                xmin = v.x

            if v.y > ymax:
                ymax = v.y
            if v.y < ymin:
                ymin = v.y

            if v.z > zmax:
                zmax = v.z
            if v.z < zmin:
                zmin = v.z
                #places the vertice in the array holding all of the vertices
                verts[a] = ver
                a = a + 1

    # find polar coordinates of selected region
    Maxvert = PhotoScan.Vector([xmax, ymax, zmax])
    Minvert = PhotoScan.Vector([xmin, ymin, zmin])

    #Scale
    Maxvert *= padding
    Minvert *= padding

    #find center of region
    Center = (Maxvert + Minvert) / 2
    #find size of region
    Size = Maxvert - Minvert

    # resize bounding area to be slightly larger than the coordinates
    region.center = Mat.inv().mulp(chunk.crs.unproject(Center))
    region.size = Size * (1 / Mat.scale())
    print(region.size)

    v_t = Mat * PhotoScan.Vector([0, 0, 0, 1])
    v_t.size = 3
    R = chunk.crs.localframe(v_t) * Mat
    region.rot = R.rotation().t()
    chunk.region = region

    #build depth maps
    chunk.buildDepthMaps(quality=PhotoScan.MediumQuality,
                         filter=PhotoScan.AggressiveFiltering)

    #build dense cloud
    chunk.buildDenseCloud()

    #build mesh
    chunk.buildModel(surface=PhotoScan.Arbitrary,
                     interpolation=PhotoScan.EnabledInterpolation)

    print("Importing masks")
    chunk.importMasks(path='',
                      source=PhotoScan.MaskSourceModel,
                      operation=PhotoScan.MaskOperationReplacement,
                      tolerance=10,
                      cameras=chunk.cameras)
    print("Script finished!")
Exemple #29
0
 sp_line = line.rsplit(",", 6)  #splitting read line by four parts
 camera_name = sp_line[0]  #camera label
 marker_name = sp_line[1]  #marker label
 x = int(sp_line[2])  #x- coordinate of the current projection in pixels
 y = int(sp_line[3])  #y- coordinate of the current projection in pixels
 cx = float(sp_line[4])  #world x- coordinate of the current marker
 cy = float(sp_line[5])  #world y- coordinate of the current marker
 cz = float(sp_line[6])  #world z- coordinate of the current marker
 flag = 0
 for i in range(0, photos_total):
     if chunk.cameras[i].label == camera_name:
         for marker in chunk.markers:  #searching for the marker (comparing with all the marker labels in chunk)
             if marker.label == marker_name:
                 marker.projections[
                     chunk.cameras[i]] = PhotoScan.Marker.Projection(
                         PhotoScan.Vector([x, y]), True
                     )  #setting up marker projection of the correct photo)
                 flag = 1
                 break
         if not flag:
             marker = chunk.addMarker()
             marker.label = marker_name
             marker.projections[
                 chunk.cameras[i]] = PhotoScan.Marker.Projection(
                     PhotoScan.Vector([x, y]), True)
             # print(marker)
         marker.reference.location = PhotoScan.Vector([cx, cy, cz])
         break
 line = markerList.readline()  #reading the line in input file
 #     print (line)
 if len(line) == 0:
Exemple #30
0
def error(_CurrentChunk):

    # Compatibility - Agisoft PhotoScan Professional 1.2.4
    # saves reprojection error for the tie points in the sparse cloud

    import PhotoScan
    import math
    doc = PhotoScan.app.document

    M = _CurrentChunk.transform.matrix
    crs = _CurrentChunk.crs
    point_cloud = _CurrentChunk.point_cloud
    projections = point_cloud.projections
    points = point_cloud.points
    npoints = len(points)
    tracks = point_cloud.tracks

    points_coords = {}
    points_errors = {}
    errorList = []

    for photo in _CurrentChunk.cameras:

        if not photo.transform:
            continue

        T = photo.transform.inv()
        calib = photo.sensor.calibration

        point_index = 0
        for proj in projections[photo]:
            track_id = proj.track_id
            while point_index < npoints and points[
                    point_index].track_id < track_id:
                point_index += 1
            if point_index < npoints and points[
                    point_index].track_id == track_id:
                if points[point_index].valid == False:
                    continue

                coord = T * points[point_index].coord
                coord.size = 3
                dist = calib.error(coord, proj.coord).norm()**2
                v = M * points[point_index].coord
                v.size = 3

                if point_index in points_errors.keys():
                    point_index = int(point_index)
                    points_errors[point_index].x += dist
                    points_errors[point_index].y += 1
                else:
                    points_errors[point_index] = PhotoScan.Vector([dist, 1])

    for point_index in range(npoints):

        if points[point_index].valid == False:
            continue

        if _CurrentChunk.crs:
            w = M * points[point_index].coord
            w.size = 3
            X, Y, Z = _CurrentChunk.crs.project(w)
        else:
            X, Y, Z, w = M * points[point_index].coord

        error = math.sqrt(points_errors[point_index].x /
                          points_errors[point_index].y)
        errorList.append(error)
        errorList.sort()

    avgError = sum(errorList) / len(
        errorList)  ###for original photos, no point manipulation recorded

    validPtList = []

    for pt in _CurrentChunk.point_cloud.points:  ##Makes a list of points that are NOT deleted
        if pt.valid == True:
            validPtList.append(pt)
        else:
            continue

    count = 0

    #for err in errorList: ## loops through error values in error list
    #    if err > 1.5*avgError:
    #        validPtList[count].selected = True
    #    count += 1

    print(avgError)
    print(max(errorList))
    return avgError