RGB 영상에서의 픽셀 데이터 구성에 대해 알아봅니다.

 

 

 

1. DICOM RGB 영상.

 

DICOM Tag PhotometricInterpretation(0028,0004)이 RGB인 영상입니다.

 

RGB 영상은 각 픽셀의 색상을 빨간색, 녹색, 파란색의 세 가지 채널로 이루어져 있으며 세 채널의 조합으로 모든 색상을 표현할 수 있습니다.

 

 

 

2. Planar Configuration

 

RGB 영상의 픽셀데이터 구성에 대해 알기 위해선 먼저 PlanarConfiguration(0028,0006) 태그를 먼저 확인해야 합니다.

 

이 태그는 DICOM 이미지에서 색상 채널 데이터가 어떻게 배열되는지를 정의하는 DICOM 태그입니다. 해당 값은 0 혹인 1로 표시되며 각각 다음을 의미합니다.

 

0인 경우 RGB 채널이 인터리브(Interleaved)하게 이루어져 있습니다. Color-by-pixel 방식이라고도 하며 모든 채널의 데이터를 교대로 저장하여 RGB 데이터가 연속된 형식으로 존재합니다. 이는 각 픽셀에 해당하는 RGB값이 연속적으로 저장됨을 뜻합니다. 예: [R0, G0, B0, R1, G1, B1, ...]

 

1인경우 RGB 채널이 플래너(Planar)하게 이루어져 있습니다. Color-by-plane 방식이라고도 합니다. 각 색상 채널이 별도의 2D 이미지로 저장되며, 각 채널이 독립적으로 배열됩니다. 이는 각 색상 채널이 개별적으로 저장되어 있음을 뜻합니다. 예: 예: [R0, R1, R2, ..., Gn, Gm, Gn+1, ..., Bn, Bm, Bn+1, ...]

 

 

 

3. BitAllocated와 BitStored

 

DICOM에서 픽셀 데이터를 다루기 위해선 또 다른 태그를 더 살펴봐야 합니다.

 

Bit Allocated(0028,0100)는 각 픽셀에 할당된 총 비트 수를 의미하며 일반적으로 8, 12, 16 비트가 사용됩니다.  Bits Stored(0028,0101)는 각 픽셀에 저장된 실제 유효 비트 수를 의미합니다.

 

예를 들어, Bits Allocated가 16이고, Bits Stored가 12이면, 각 픽셀 데이터는 16비트로 저장되지만, 그중 12비트만 유효 데이터로 사용됩니다. 나머지 4비트는 일반적으로 0으로 채워짐을 의미합니다.

 

 

 

4. 픽셀 데이터 계산

 

이제 기본적인 태그(rows 및 colums)를 사용해 RGB 영상의 픽셀 데이터 위치를 알아낼 수 있습니다. 

 

PlanarConfiguration이 1일 때 rows(H)와 columns(W)가 512인 경우 x, y좌표 300, 250의 RGB값은 다음과 같이 구할 수 있습니다.

    ⇒ 한 프레임의 픽셀 수: W x H
    ⇒ 한 프레임의 채널 데이터 크기: W x H
    ⇒ 한 프레임의 전체 데이터 크기: 3 x W x H

여기서 각 프레임의 데이터는 연속적으로 저장되므로, N번째 프레임의 시작 위치는 다음과 같이 계산할 수 있습니다

    ⇒ N번째 프레임의 시작 위치: (N-1) * 3 * W * H

PlanarConfiguration이 1이므로 각채널의 시작위치는 다음과 같이 유추할 수 있습니다.

    ⇒  Red 채널의 시작 위치: (N-1) * 3 * W * H
    ⇒  Green 채널의 시작 위치: (N-1) * 3 * W * H + W * H
    ⇒  Blue 채널의 시작 위치: (N-1) * 3 * W * H + 2 * W * H

마지막으로 실제 우리가 원하는 픽셀의 인덱스 위치는 다음과 같이 계산할 수 있습니다.

    ⇒ 픽셀 인덱스: y * W + x

따라서 위의 모든 식을 종합하면 PlanarConfiguration이 1일 때 rows(H)와 columns(W)가 512인 경우 x, y좌표 300, 250의 RGB의 위치는 다음과 같이 산출됩니다.

    ⇒ Red 값의 위치: (N-1) * ( 3 x W x H)+ (y * W + x)
    ⇒ Green 값의 위치: (N-1) * ( 3 x W x H) + (W * H)+ (y * W + x)
    ⇒ Blue 값의 위치: (N-1) * ( 3 x W x H) + (2 * W * H) + (y * W + x)

 

다음으로 PlanarConfiguration이 0일 때 rows(H)와 columns(W)가 512인 경우 x, y좌표 300, 250의 RGB값은 다음과 같이 구할 수 있습니다.

    ⇒ 한 프레임의 픽셀 수: W x H
    ⇒ 한 프레임의 전체 데이터 크기: 3 x W x H

여기서 각 프레임의 데이터는 연속적으로 저장되므로, N번째 프레임의 시작 위치는 다음과 같이 계산할 수 있습니다

    ⇒ N번째 프레임의 시작 위치: (N-1) * 3 * W * H

다음으로 우리가 원하는 픽셀의 인덱스 위치는 다음과 같이 계산할 수 있습니다.

    ⇒ 픽셀 인덱스: y * W + x

PlanarConfiguration이 0이므로, 각 픽셀의 R, G, B 값이 연속적으로 저장됩니다. 따라서, N번째 프레임의 시작 위치에서 해당 픽셀 인덱스를 3배 한 값이 각 채널의 시작 위치가 됩니다.

    ⇒ Red   값의 위치: (N-1) * (3 * W * H) + 3 * (y * W + x)
    ⇒ Green   값의 위치: (N-1) * (3 * W * H) + 3 *  (y * W + x) + 1
    ⇒ Blue   값의 위치: (N-1) * (3 * W * H) + 3 *  (y * W + x) + 2

 

이제 해당 값을 이용해 픽셀 데이터를 원하는 값으로 수정할 수 있습니다.

 

 

 

 

 

 

반응형

 

 

 

Keyclock 컨테이너를 postgresql db와 함께 사용하는 방법에 대하 알아봅니다.

 

 

 

0. 참고

 

jbos/keycloak는 더 이상 관리되지 않습니다. 현재 글 작성 시점에 dockerhub에는 공식 keycloak 이미지가 배포되고 있지 않습니다. 

 

 

 

1. docker-compose.yml

 

다음과 같이 docker-compose.yml을 작성합니다.

 

version: '3.8'

services:
  keycloak:
    image: quay.io/keycloak/keycloak:24.0.2
    ports:
      - "8080:8080"
    environment:
      KC_DB: postgres
      KC_DB_URL: jdbc:postgresql://your.dbhost.com:5432/yourdbname
      KC_DB_USERNAME: yourdbuser
      KC_DB_PASSWORD: yourdbpassword
      KC_HTTP_ENABLED: true
      KC_HEALTH_ENABLED: true
      KEYCLOAK_ADMIN: yourkeycloakuser
      KEYCLOAK_ADMIN_PASSWORD: yourkeycloakpassword
    command: 
      - start-dev 
      - --import-realm
    volumes:
      - /home/keycloak/realm.json:/opt/keycloak/data/import/realm.json

 

환경 변수에대해 간단하게 설명하자면 다음과 같습니다.

  • KC_DB: 사용할 데이터베이스의 종류입니다. postgres로 두면 됩니다.
  • KC_DB_URL: postgres 접속 정보입니다. host, port, db이름을 변경해 사용하시면 됩니다.
  • KC_DB_USERNAME: DB 접속 계정 정보입니다. 변경해 사용하시면 됩니다.
  • KC_DB_PASSWORD: DB 접속 계정의 암호입니다. 변경해 사용하시면 됩니다.
  • KC_HTTP_ENABLE: HTTP를 통해 접근 가능한지 여부를 결정합니다. 
  • KC_HEALTH_ENABLED: 상태 확인 엔드포인트를 활성화할지 여부를 결정합니다. true로 설정한 경우 다음과 같은 엔드포인트가 활성화됩니다.
    • /health/live
    • /health/ready
    • /health/started
    • /health
  • KEYCLOAK_ADMIN: 관리용 페이지에 로그인할 수 있는 계정을 설정합니다.
  • KEYCLOAK_ADMIN_PASSWORD: 관리용 페이지에 로그인 할 수 있는 계정의 암호를 설정합니다.

 

 

 

 

 

반응형

 

 

 

일반적으로 lib는 C++에서, dll은 양쪽 모두에서 사용할 수 있는 라이브러리 산출물로 알려져 있습니다.

그동안 이를 당연하게 여기고 별 의문 없이 관습적으로, 사용하던 대로 사용하곤 했습니다.

이 글에선 lib와 dll이 무엇이고 어떤점이 다르길래 왜 C#에선 lib를 사용할 수 없는지 알아보고자 합니다.

 

 

 

.lib와 .dll 파일

 

.dll 파일과 .lib 파일은 모두 C++ 프로그래밍에서 사용되는 파일 형식입니다. 하지만 그들의 역할과 구성은 다릅니다.

 

.dll 파일은 실행 중에 다른 프로그램에 의해 호출되는 코드와 데이터의 모음입니다. 이는 동적 라이브러리라고 부르며 프로그램이 실행될 때에만 필요한 함수 및 데이터를 메모리에 로드합니다.
여러 프로그램에서 공유하여 사용할 수 있으며, 코드 및 데이터의 재사용을 용이하게 합니다. dll은 주로 라이브러리나 플러그인 형태로 사용되며, 함수와 데이터를 외부에 공개하기 위한 인터페이스 역할을 합니다.

 

.lib 파일은 프로그램이 컴파일될 때 링커(Linker)에 의해 사용되는 라이브러리 파일입니다. 정적 라이브러리라고 부르며 해당 파일에 포함된 코드와 데이터가 컴파일 시에 프로그램에 직접 포함됩니다.
프로그램을 실행할 때 .lib 파일이 필요하지 않으며, 해당 파일에 포함된 코드 및 데이터가 이미 실행 파일에 포함되어 있습니다. 주로 컴파일러에 의해 생성된 객체 파일(Object File)을 묶어 놓은 형태로 사용되며, 함수 및 데이터의 정의를 포함합니다.

 

주요한 차이점은 .dll 파일이 실행 중에 필요한 코드와 데이터를 제공하는 동적 라이브러리인 반면, .lib 파일은 컴파일 시에 링크되는 정적 라이브러리입니다. 또한 .dll 파일은 외부 프로그램에서 호출되고 공유될 수 있지만, .lib 파일은 컴파일 시에 해당 프로그램에 포함되어 실행된다는 점 입니다.

 

 

 

그래서 왜 C#에서는 lib 파일을 사용할 수 없을까?

 

.lib 파일은 C++에서 사용되는 라이브러리 파일로, 컴파일러에 의해 링크되어 프로그램에 포함됩니다. 이 파일은 주로 함수와 기호의 정의를 포함하고 있을 뿐 .lib 파일 자체는 실행 코드를 포함하고 있지 않습니다.

C++에서는 컴파일 시에 .lib 파일이 필요하며, 링크 과정에서 이 파일이 사용됩니다. 그러나 C#은 .NET Framework 또는 .NET Core와 같은 가상 머신 위에서 실행되는 고수준 언어로, 직접적으로 .lib 파일을 사용하는 것은 불가능합니다.

대신에, C#에서는 Platform Invocation Services(P/Invoke)를 통해 외부 DLL에 있는 함수들을 호출할 수 있습니다. 따라서 .lib 파일을 사용하는 대신 해당 .lib 파일로부터 생성된 DLL 파일을 사용하여 P/Invoke를 통해 함수를 호출해야 합니다.

길지만 결국 근본적으로는 언어 및 런타임 환경이 서로 다르기 때문입니다.

 

C# 코드는 CLR(Common Language Runtime)이라고 불리는 가상 머신에서 실행됩니다. 이는 메모리 관리, 예외 처리 및 스레드 관리와 같은 기능을 제공합니다. 반면에 C++ 코드는 운영체제의 네이티브 코드로 컴파일되어 실행됩니다.

 

따라서 C#에서는 .lib 파일에 포함된 네이티브 코드를 직접적으로 이해하고 호출할 수 없습니다. 대신에, C#에서는 P/Invoke를 사용하여 외부 DLL 파일에 포함된 함수들을 호출할 수 있습니다. 이렇게 함으로써 C#은 외부 C++ 코드와 상호작용할 수 있습니다.

 

 

 

 

반응형

+ Recent posts