Category: Python

  • MRI로 mesh 만들기

    기존의 알려진 방법을 기초로 시도했다.

    결론부터 말하면 기존 알고리즘으로는 아쉬운 부분이 존재한다. 제대로 만들기 위해서는 한 땀 한 땀 mesh 를 작성해야 할 필요가 있다.

    Brain MRI 중 T1 TRA SE 이미지가 적당해서 이걸로 선택했다. 한 장씩 DICOM 저장해서 확인한다. 익명성을 위해서 UUID를 이용해 버리는 바람에 DICOM에 포함된 Image Position 정보를 이용해서 순서대로 정렬시켜야 한다. Image Position 의 3번째 값이 머리-> 꼬리 방향과 연관된 정보이다.

    MRI에는 CT 처럼 HU 값이 없다. 그냥 바탕의 적당한 값을 기준으로 어두운 부분은 False 있는 부분은 True 형식으로 변환시켰다. 적절한 처리를 거치면 이렇게 얼굴의 윗 부분을 만들 수 있다.

    이 Numpy matrix에서 점에 대한 정보만 있어야 한다. Copilot에서 물어봤더니 약간 수정해야 하지만 매우 편한 스크립트를 짜주었다.

    points = []
    for x in range(blk.shape[0]):
        for y in range(blk.shape[1]):
            for z in range(blk.shape[2]):
                if blk[x, y, z] > 0:
                    points.append([x, y, z])
    
    points = numpy.array(points)

    Open3D 패키지를 이용해서 point cloud를 만들어 준다.

    pcd = open3d.geometry.PointCloud()
    pcd.points = open3d.utility.Vector3dVector(points)

    mesh 를 만들기 위해서는 법선(normal)이 있어야 한다. 당연히 이 정보는 없으니까 만들어 주어야 한다. pcd.has_normals() 을 이용해서 normal 이 있는지 알 수 있다. 없으면 estimate_normals() 을 이용하여 만들어 줄 수도 있다.

    if pcd.has_normals():
        pcd.normals = ...
    else:
        pcd.estimate_normals()

    BPA는 다음 처럼

    ## BPA
    distances = pcd.compute_nearest_neighbor_distance()
    radius = 10
    bpa_mesh = open3d.geometry.TriangleMesh.create_from_point_cloud_ball_pivoting(pcd, open3d.utility.DoubleVector([radius, radius * 2]))
    print(open3d.io.write_triangle_mesh("/root/3D/head_bpa.ply", bpa_mesh))

    Poisson은 다음 처럼

    poisson_mesh, densities = open3d.geometry.TriangleMesh.create_from_point_cloud_poisson(pcd, depth=9)
    bbox = pcd.get_axis_aligned_bounding_box() 
    p_mesh_crop = poisson_mesh.crop(bbox)

    이런 느낌으로 mesh를 만들 수 있다. 위에서도 언급했지만 두 방법 모두 mesh가 빠지는 부분이 있다.

  • Point clouds로 Mesh 생성하기

    한 땀 한 땀 만들어야 하나 고민하고 있었는데 누군가가 이미 구현해둔 방법들이 있는 것을 알게 되었다.

    jupyterlab 환경에서는 안된 것 같다. 좀 더 확인해 볼 필요가 있다. 얼핏 검색해 본 바에 의하면 numpy 버전을 1.대로 낮추어 야 할 필요가 있는 것 같다.

    Numpy 버전을 낮추는 방법은 다시 설치를 하면 된다.

    pip install numpy==1.26.4 --break-system-packages
  • quadrilateral mesh

    copilot에서 4각형 메시를 만들어 달라고 해보았다.

    # 사각형 메쉬 예제
    
    # 정점 정의 (v x y z)
    v 0.0 0.0 0.0
    v 1.0 0.0 0.0
    v 1.0 1.0 0.0
    v 0.0 1.0 0.0
    
    # 면 정의 (f vertex1 vertex2 vertex3 vertex4)
    f 1 2 3 4

    이걸 보면 다음과 같다.

    각각의 점(v)에 대한 정의를 이용해서 면(f)을 만들어 낸다. 문제는 점의 좌표를 다 파악하고 있어야 한다.

    면에서 4개의 점을 입력하면 사각형이, 6개의 점을 입력하면 육각형을 만들 수 있다.

    copilot에서 인덱스 없이 만들 수 있는 방법을 물어 보았다. 방법을 알려주는데 그 방법은 제대로 동작하지 않는 것 같다. 인덱스를 활영해서 하는 것이 좋겠다.첫 번째가 0이 아닌 1이다. point cloud에서 obj 등과 같이 변환해 주는 것들이 있기는 한데.. 무료가 아닌 것 같다. 그러면 천천해 만들어 봐야한다. 표면이 단순하다는게 다행이긴 하다.

  • Datamatrix

    회사에서 접수 때 사용하는 바코드의 정보는 2가지이다. 하나는 환자 번호가 있는 것, 다른 하나는 검체 번호가 있는 것이다.

    병리과에서 문제라면 생검 조직은 둥근 통에 담기는데 바코드를 세워 붙여야 인식이 잘 된다는 것이다. 일부 바코드는 Datamatrix 형식으로 운영되니 여기에 맞춰서 작업을 해보기로 한다. 우선 직접 datamatrix를 만들 수 있어야 하니 이것부터 시도했다.

    treepoem 패키지를 이용한다.

    여기에 보면 datamatrix를 만들 수 있다는 내용은 없는데 만들 수 있다. 다만, 기존에 사용하던 것이랑 표현이 조금 달라서 더 알아봐야 한다.

    import treepoem
    
    image = treepoem.generate_barcode(
        barcode_type="datamatrix",  # One of the BWIPP supported codes.
        data="12345678",
    )
    image.convert("1").save("qr.png")