https://fpcv.cs.columbia.edu/ 

알고리즘은 컴퓨터 전 및 이미지 처리에서 주요한 역할을 합니다.

 

 

ORB (Oriented FAST and Rotated BRIEF):

 

 

1. FAST(FeaturesfromAcceleratedSegmentTest)기와BRIEF(BinaryRobustIndependent Elementary Features) 자의 합입니다.

2. FAST를 사하여 르게 특점을 하고, BRIEF를 사하여 특점 주변의 특설명합니다.

3. 회전에 변한 특설명을 제공합니다.
4. ORB
SIFT SURF더 빠르지만, 적으로 한 결과를 제공합니다.

 

import cv2

# 동영상 파일 열기
cap = cv2.VideoCapture("MS/CV/0612 객체탐지,추적/data/vtest.avi")

# ORB 객체 생성
orb = cv2.ORB_create()

while True:
    # 프레임 읽기
    ret, frame = cap.read()
    if not ret:
        break
        
    # 그레이스케일로 변환
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # 특징점 검출
    keypoints = orb.detect(gray, None)

    # 특징점 그리기
    frame = cv2.drawKeypoints(frame, keypoints, None, (0, 150, 220), flags=0)

    # 출력
    cv2.imshow("ORB", frame)
    if cv2.waitKey(30) & 0xFF == ord("q"):
        break

cap.release()
cv2.destroyAllWindows()

를 쓰면 불필요한 특징점도 많이 나온다.

 

Mask를 활용하여 특징점 제거하기 2

 

 

import cv2
import numpy as np

# 동영상 파일 읽기
cap = cv2.VideoCapture("MS/CV/0612 객체탐지,추적/data/vtest.avi")

# ORB 객체 생성
orb = cv2.ORB_create()

# 특징점 최소 크기 설정
min_keypoint_size = 10

# 중복 특징점 제거 기준거리
duplicate_threshold = 10

while True:
    # 프레임 읽기
    ret, frame = cap.read()
    if not ret:
        break

    # 그레이스케일로 변환
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # 특징점 검출
    keypoints = orb.detect(gray, None)

    # 특징점 크기가 일정 크기 이상인 것만 남기기
    keypoints = [kp for kp in keypoints if kp.size > min_keypoint_size]  # 리스트 컴프리헨션(파이썬문법)

    # 중복된 특징점 제거
    mask = np.ones(len(keypoints), dtype=bool)  # 1차원 배열
    for i, kp1 in enumerate(keypoints):
        if mask[i]:
            for j, kp2 in enumerate(keypoints[i + 1:]):
                if (
                    mask[ i + j + 1]
                    and np.linalg.norm(np.array(kp1.pt) - np.array(kp2.pt)) < duplicate_threshold  # .pt : OpenCV의 KeyPoint 객체의 속성중 하나
                ):
                    mask[ i + j + 1] = False
    
    # kp1.pt와 kp2.pt는 각각 두 개의 키포인트 객체인 kp1과 kp2의 위치 좌표를 나타냅니다.
    """
 먼저, mask라는 길이가 keypoints의 길이와 동일한 불리언 배열을 생성합니다. 이 배열은 모든 원소를 True로 초기 화합니다.
그런 다음, keypoints 리스트를 반복하면서 현재 키포인트와 나머지 키포인트들 간의 거리를 계산하여 중복된 키포 인트를 확인합니다. 
중복된 키포인트인 경우에는 해당 키포인트에 해당하는 mask의 원소를 False로 설정합니다.
마지막으로, mask를 기반으로 중복되지 않은 키포인트들만을 새로운 리스트로 필터링하여 keypoints를 업데이트 합니다.
이를 통해 중복된 특징점을 제거하고 유니크한 특징점만을 남기는 작업을 수행합니다.
    
    """
    keypoints = [kp for i, kp in enumerate(keypoints) if mask[i]]

    # 특징점 그리기
    frame = cv2.drawKeypoints(frame, keypoints, None, (0, 200, 150), flags=0)

    cv2.imshow("ORB", frame)


    # 'q'를 누르면 종료
    if cv2.waitKey(60) == ord('q'):
        break

# 해제
cap.release()
cv2.destroyAllWindows()

 

 

 

 

알고리즘은 컴퓨터 전 및 이미지 처리에서 주요한 역할을 합니다.

SIFT (Scale-Invariant Feature Transform):

 

1. 크기 및 회전에 변한 특설명 알고리즘입니다.

2. 다양한 크기와 회전에서 특점을 하고,점 주변의 지역 특을 기합니다.

3. 점 간의 일기 위해 특점 기자를 사합니다.
4. SIFT
우 강력한 특및 일알고리즘으로 알져 있습니다.

 

 

import cv2

# 동영상 파읽 열기
cap = cv2.VideoCapture("MS/CV/0612 객체탐지,추적/data/slow_traffic_small.mp4")

# sift 객체 생성
sift = cv2.SIFT_create()

while True:
    # 프레임 읽기
    ret, frame = cap.read()
    if not ret:
        break

    # 그레이스케일로 변환
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # 특징점 검출
    keypoints, descriptors = sift.detectAndCompute(gray, None)

    # 특징점 그리기
    frame = cv2.drawKeypoints(frame, keypoints, None,
                              flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

    # 화면에 출력
    cv2.imshow("frame", frame)

    # 'q'를 누르면 종료
    if cv2.waitKey(60) == ord('q'):
        break

# 해제
cap.release()
cv2.destroyAllWindows()

 

 

개수제한 >>>

 

1. 이미지 대비 밝기 일정이상의 차이가 있을때만 보이게 하면서

2. 포인터를 수를 일정 수로 제한해서 포인터의 개수를 특정 객체에만 나타나게 설정

 

import cv2

cap = cv2.VideoCapture("MS/CV/0612 객체탐지,추적/data/slow_traffic_small.mp4")

# SIFT 객체 생성
sift = cv2.SIFT_create(contrastThreshold=0.02)   # 이미지 대비의 밝기 차이

# 특지점 개수 제한 설정
max_keypoints = 100  # 100개의 특징점만 검출

while True:
    # 프레임 읽기
    ret, frame = cap.read()
    if not ret:
        break

    # 그레이스케일로 변환
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # 특징점 검출
    keypoints, descriptors = sift.detectAndCompute(gray, None)

    # 특징점 제한
    if len(keypoints) > max_keypoints:
        keypoints = sorted(keypoints, key=lambda x: -
                           x.response)[:max_keypoints]


    """
    keypoints = sorted(keypoints, key=lambda x: -x.response): 
    keypoints 리스트를 x.response를 기준으로 내림차순으로 정렬
    이는 키포인트의 response 값을 기준으로 정렬하겠다는 의미
    response 값이 큰 키포인트일수록 우선순위를 가지게 됩니다

    [:max_keypoints]: 정렬된 keypoints 리스트에서 처음부터 max_keypoints까지의 키포인트만 선택 
    이를 통해 최대 키포인트 수를 제한합니다.
    """
    
    
    # 특징점 그리기
    frame = cv2.drawKeypoints(frame, keypoints, None,
                              flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

    # 프레임 출력
    cv2.imshow("frame", frame)

    # 'q'를 누르면 종료
    if cv2.waitKey(60) == ord('q'):
        break

# 해제
cap.release()
cv2.destroyAllWindows()

 

 

# 객체 추적 알고리즘 소

움직이는 객체식별하고, 그 위적하는 방법을 의미합니다. 이를 해 동상이나 실시간 스트리데 이터에서 객체움직지하고, 객체적하는데 사됩니다. 다음은 일적으로 사되는 몇 가지 객 체 추적 알고리즘입니다.

 

점 기반 추(Feature-based Tracking):

  1. 점기반 추적은객 체의 특점을 하고, 이를 기으로 객체적합니다.
  2. SIFT (Scale-Invariant Feature Transform), SURF (Speeded-Up Robust Features), ORB (Oriented FAST and Rotated BRIEF) 등의 알고리즘을 사하여 특점을 합니다.
  3. 이 특점들은 다음 프에서 아지며, 객체움직적합니다.
  4. 점의 일도와 거리를 기으로 가장 좋은는 알고리즘을 사합니다.

 

# 점 기반 추

점 기반 추(Feature-based Tracking)에서 일적으로 르는 서는 다음과 같습니다

기화 :
1.
이미지로 변합니다.
2. Shi-Tomasi
기 또는 다방법을 사하여 적 지점을합니다.

3. 적할 특점의 기위를 저장합니다.

 

 

import cv2
import numpy as np

# 동영상 파일 읽기
cap = cv2.VideoCapture("MS/CV/0612 객체탐지,추적/data/slow_traffic_small.mp4")

# 코너 검출기 파라미터 설정
feature_params = dict(maxCorners=100, qualityLevel=0.3,
                      minDistance=7, blockSize=7)
"""
maxCorners: 검출할 최대 특징점 수를 지정. 여기서는 최대 100개의 특징점을 검출하도록 설정
qualityLevel: 특징점으로 인정되기 위한 품질 기준. 0과 1 사이의 값,높을수록 특징점으로 인정되기 위한 조건이 엄격
minDistance: 검출된 특징점들 간의 최소 거리를 나타냄 이 거리보다 가까운 특징점은 제거
blockSize: 특징점 검출 시 사용되는 이웃 픽셀 블록의 크기. 특징점 검출 알고리즘에서 사용되는 계산에 영향을 미치는 요소
"""


# 광학 흐름 파라미터 설정
lk_params = dict(winSize=(30, 30), maxLevel=2, criteria=( # 알고리즘 중지기준
    cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))  # eps정확도가 criteria[0]보다 작을때까지 or count는 반복회수가 criteria[1]보다 작을때 까지 추적
"""
winSize=(30, 30): 이동 벡터를 추정하기 위해 사용되는 윈도우(window)의 크기
윈도우 크기는 광학 흐름 알고리즘에서 이웃 픽셀들 간의 관계를 분석하는 데 사용되는 영역의 크기를 조절 

maxLevel=2: 피라미드 계층의 수
광학 흐름 알고리즘은 다단계의 피라미드 구조를 사용하여 이미지의 해상도를 다양하게 처리


"""
    

# 첫 프레임 읽기
ret, next_frame = cap.read()
prev_gray = cv2.cvtColor(next_frame, cv2.COLOR_BGR2GRAY)

# 초기 추적 지점 선택
prev_corners = cv2.goodFeaturesToTrack(prev_gray, mask=None, **feature_params)
prev_points = prev_corners.squeeze()

# 추적 결과를 표시하기위한 색상 설정
color = (0, 200, 0)

while True:
    # 다음 프레임 읽기
    ret, next_frame = cap.read()
    if not ret:
        break

    # 현재 프레임 변환
    gray = cv2.cvtColor(next_frame, cv2.COLOR_BGR2GRAY)

    # 옵티컬 플로우 계산
    next_points, status, err = cv2.calcOpticalFlowPyrLK(
        prev_gray, gray, prev_points, None, **lk_params)

    # 추적 결과를 좋은 포인트로 필터링
    for i, (prev_point, next_point) in enumerate(zip(prev_points, next_points)):
        x_prev, y_prev = prev_point.astype(np.int32)
        x_next, y_next = next_point.astype(np.int32)

        # cv2.line(prev_frame, (x_prev, y_prev), (x_next, y_next), color, 2)
        cv2.circle(next_frame, (x_next, y_next), 3, color, 3)

    # 화면에 출력
    cv2.imshow("OpticalFlow-LK", next_frame)

    # 다음 프레임을 위한 프레임과 포인트 저장
    prev_gray = gray.copy()
    prev_points = next_points

    # 'q'를 누르면 종료
    if cv2.waitKey(60) == ord('q'):
        break

# 해제
cap.release()
cv2.destroyAllWindows()

# 객체 추적 알고리즘 소

움직이는 객체식별하고, 그 위적하는 방법을 의미합니다. 이를 해 동상이나 실시간 스트리데 이터에서 객체움직지하고, 객체적하는데 사됩니다. 다음은 일적으로 사되는 몇 가지 객 체 추적 알고리즘입니다.

 

만 필터 (Kalman Filter Tracking):


1.
만필터는 상태정에 사되는 필터, 객체추적에도 적됩니다.
2.
예측과 실제관을 기으로 객체의 위와 속도를 정합니다.
3.
예측과 관간의 오를 고하여 정한 위를 업데이트합니다.
4.
이를 움직이는 객체의 경로를 적하고, 예측불확실성을 줄입니다.

 

측정 행렬(Measurement Matrix): 측정 행렬은 시스템의 상태를 측정값으로 변환하는 역할을 합니다. 측정 행렬은 상태 벡터와 측정 벡터 사이의 선형 변환을 정의합니다. 일반적으로 센서로부터 얻은 측정값을 상태 벡터의 선형 조합으로 표현하는 데 사용됩니다. 측정 행렬은 시스템의 동작과 측정 방식에 따라 결정되며, 변하지 않는 고정된 행렬입니다.

전이 행렬(Transition Matrix): 전이 행렬은 시스템의 상태를 현재 상태에서 다음 상태로 변환하는 역할을 합니다. 전이 행렬은 시스템의 동적 모델을 반영하여 상태 벡터를 현재 상태에서 다음 상태로 예측하는 데 사용됩니다. 전이 행렬은 시간에 따라 변할 수 있으며, 시스템의 동작을 모델링하는 데 사용되는 다른 행렬들과 연결되어 시스템의 상태 추정에 영향을 미칩니다.

 

import cv2
import numpy as np

# kalman filter
kalman = cv2.KalmanFilter(4,2)  # 상태백터(위치와 속도 등)를 4차원으로 지정, 측정벡터(센서신호) 2차원으로 세팅) 

# 측정 행렬을 설정합니다. 이 행렬은 측정 벡터를 상태 벡터로 변환하는 역할
kalman.measurementMatrix = np.array([[1,0,0,0],[0,1,0,0]],np.float32)  
# 전이 행렬을 설정합니다. 이 행 렬은 시간에 따라 상태 벡터가 어떻게 변화하는지를 나타냄
kalman.transitionMatrix = np.array([[1,0,1,0],[0,1,0,1],[0,0,1,0],[0,0,0,1]],np.float32) 
# 프로세스 잡음 공분산 행렬을 설정합니다. 이 값은 시스템의 불확실성을 모델링
kalman.processNoiseCov = np.array([[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],np.float32) * 0.05


# 칼만 필터 추적 실습
# 영상 파일 열기
cap = cv2.VideoCapture("MS/데이터전처리/0612/data/slow_traffic_small.mp4")

# 첫 프레임에서 추적할 객체 선택
ret, frame = cap.read()
print(ret, frame) # 경로가 잘못된 경우 ret = False, frame = None / 정상일경우 ret = True, frame = 영상프레임

x, y, w, h = cv2.selectROI(frame, False, False)

"""
"Select Object": 객체를 선택할 때 표시될 창의 제목입니다.
frame: 이미지나 비디오 프레임을 나타내는 변수입니다.
False: 선택한 영역을 자동으로 크롭하지 않고, 선택한 영역의 좌표와 크기를 반환합니다.
False: 마우스 이벤트를 사용하여 객체의 영역을 선택할 수 있도록 합니다.
"""
print("선택한 박스의 좌표 >>", x, y, w, h)

# 객체 추적을 위한 초기 추정 위치 설정
# 객체의 x,y,x방향속도(초기0), y방향속도(초기0)로 지정  # 일단 속도를 알 수 없으니 0으로 초기화
kalman.statePre = np.array([[x],[y],[0],[0]],np.float32)

while True:
    # 프레임 읽기
    ret, frame = cap.read()
    if not ret:
        break

    # 칼만 필터로 예측한 위치 계산
    kalman.correct(np.array([[np.float32(x)+w/2],[np.float32(y)+h/2]]))
    kalman.predict()

    # 칼만 필터로 추정된 객체 위치
    predicted_bbox = tuple(map(int, kalman.statePost[:2,0]))
    """
    map(int, kalman.statePost[:2,0]): 상태 벡터의 값들을 int 함수를 사용하여 정수로 변환 
    map 함수는 시퀀스의 모든 요소에 함수를 적용하여 새로운 시퀀스를 생성 
    여기서는 상태 벡터의 값을 int 함수를 사용하여 정수로 변환
    """

    # 추정된 위치에 사각형 그리기
    cv2.rectangle(frame, (predicted_bbox[0]-w//2, predicted_bbox[1]-h//2), 
                        (predicted_bbox[0]+w//2, predicted_bbox[1]+h//2), 
                        (0,255,255), 2)

    # 화면에 출력
    cv2.imshow("frame", frame)


    # 'q'를 누르면 종료
    if cv2.waitKey(60) == ord('q'):
        break

# 해제
cap.release()
cv2.destroyAllWindows()

 

 

 

import cv2
import numpy as np

# kalman filter
kalman = cv2.KalmanFilter(4,2)
kalman.measurementMatrix = np.array([[1,0,0,0],
                                    [0,1,0,0]],np.float32)
kalman.transitionMatrix = np.array([[1,0,1,0],[0,1,0,1],[0,0,1,0],[0,0,0,1]],np.float32)
kalman.processNoiseCov = np.array([[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],np.float32) * 0.05

# 칼만 필터 추적 실습
# 영상 파일 열기
cap = cv2.VideoCapture("MS/데이터전처리/0612/data/slow_traffic_small.mp4")

# 첫 프레임에서 추적할 객체 선택
ret, frame = cap.read()
print(ret, frame) # 경로가 잘못된 경우 ret = False, frame = None / 정상일경우 ret = True, frame = 영상프레임

x, y, w, h = cv2.selectROI(frame, False, False)
print("선택한 박스의 좌표 >>", x, y, w, h)

# 객체 추적을 위한 초기 추정 위치 설정
# 객체의 x,y,x방향속도(초기0), y방향속도(초기0)
kalman.statePre = np.array([[x],[y],[0],[0]],np.float32)

while True:
    # 프레임 읽기
    ret, frame = cap.read()
    if not ret:
        break

    # 칼만 필터로 예측한 위치 계산
    kalman.correct(np.array([[np.float32(x)+w/2],[np.float32(y)+h/2]]))
    kalman.predict()

    # 칼만 필터로 추정된 객체 위치
    predicted_bbox = tuple(map(int, kalman.statePost[:2,0]))

    # 추정된 위치에 사각형 그리기
    cv2.rectangle(frame, (predicted_bbox[0]-w//2, predicted_bbox[1]-h//2), 
                        (predicted_bbox[0]+w//2, predicted_bbox[1]+h//2), 
                        (0,255,255), 2)

    # 화면에 출력
    cv2.imshow("frame", frame)


    # 'q'를 누르면 종료
    if cv2.waitKey(60) == ord('q'):
        break

# 해제
cap.release()
cv2.destroyAllWindows()

 

# 객체 추적 알고리즘 소

움직이는 객체식별하고, 그 위적하는 방법을 의미합니다. 이를 해 동상이나 실시간 스트리데 이터에서 객체움직지하고, 객체적하는데 사됩니다. 다음은 일적으로 사되는 몇 가지 객 체 추적 알고리즘입니다.

 

평균 이동 추적 (Mean Shift Tracking):

1. 평균 이동추적은 객체의 히스토그램을 기반으로 추적하는 알고리즘입니다.
2. 초기위치를 선택하고, 해당 위치의 픽셀분포를 히스토그램으로 계산합니다.
3. 다음 프레임에서 히스토그램 유사도를 측정하여 객체의 새로운 위치를 찾습니다.

4. 이 과정을 반복하여 객체움직적합니다.

우선 전체 코드

 

import cv2

# 평균 이동 추적을 위한 초기 사각형 설정
track_window = None  # 객체의 위치 정보 저장할 변수
roi_hist = None  # 히스토그램을 저장할 변수
trem_crit = (cv2.TERM_CRITERIA_EPS|cv2.TERM_CRITERIA_COUNT, 10,1)  # 반복횟수 10

"""
cv2.TERM_CRITERIA_EPS: 반복 알고리즘의 정지 기준 중 하나로, 
주어진 정지 기준 오차(epsilon)를 충족하는 경우 알고리즘을 중지합니다.
cv2.TERM_CRITERIA_COUNT: 반복 알고리즘의 정지 기준 중 하나로, 
주어진 반복 횟수(count)를 충족하는 경우 알고리즘을 중지합니다.
따라서 cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT는 이 두 가지 정지 기준을 모두 사용하겠다는 의미입니다. 
이러한 정지 기준을 설정한 후에는 알고리즘이 주어진 정지 기준에 도달하면 반복을 중지하게 됩니다.

또한, (10, 1)은 알고리즘의 최대 반복 횟수와 정지 기준 오차(epsilon) 값을 나타냅니다. 
예를 들어, 여기서는 최대 10번의 반복과 1의 정지 기준 오차를 설정하였습니다. 
따라서 알고리즘은 최대 10번 반복하거나 주어진 오차가 1 이하로 감소할 때까지 실행됩니다.
"""


# 영상 파일 열기 
cap = cv2.VideoCapture("MS/데이터전처리/0612/data/slow_traffic_small.mp4")

# 첫 프레임에서 추적할 객체 선택
ret, frame = cap.read()  # 영상 있냐없냐 T/F가 ret , Frame 저장
x, y, w, h = cv2.selectROI("selectROI", frame, False, False)
print("선택한 박스의 좌표 >>", x, y, w, h)


# 추적할 객체 초기 히스토그램 계산
roi = frame[y:y+h, x:x+w]  # 관심구역
hsv_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV) # (Hue 색상, Saturation 채도, Value 명도)
roi_hist = cv2.calcHist([hsv_roi], [0], None, [180], [0,180]) # 히스토그램 계산
cv2.normalize(roi_hist, roi_hist, 0, 255, cv2.NORM_MINMAX) # 히스토그램을 0부터 255로 정규화 (정확도 높일려고)

# 추적할 객체의 초기 윈도우 설정 
track_window = (x, y, w, h)
# cv2.imshow("roi test", roi)
# cv2.waitKey(0)

# 평균 이동 추적
while True:
    # 프레임 읽기
    ret, frame = cap.read()
    if not ret:  
        break

    # 추적할 객체에 대한 채도 히스토그램 역투영계산
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    backproj = cv2.calcBackProject([hsv], [0], roi_hist, [0,180], 1)
    """
    [hsv]: 역투영을 계산할 대상 이미지의 HSV 채널입니다. HSV 채널은 색상 정보를 갖고 있어 역투영에 활용됩니다.
    [0]: 역투영에 사용할 채널 인덱스입니다. 여기서는 색상 채널(Hue)인 0번 인덱스를 사용합니다.
    roi_hist: ROI(Region of Interest)의 히스토그램입니다. 이 히스토그램은 역투영에 사용됩니다.
    [0,180]: 히스토그램의 범위를 나타냅니다. 여기서는 Hue 채널의 범위가 0부터 180까지로 설정되었습니다.
    1: 확대 비율(scale)입니다. 픽셀의 값을 히스토그램의 값으로 나누어 정규화합니다.
    """
    

    # 평균 이동으로 새 위치 검색
    ret, track_window = cv2.meanShift(backproj, track_window, trem_crit)

    # 검색된 새 위치에 사각형 그리기
    x, y, w, h = track_window
    print("새 위치 좌표 >>", x, y, w, h)
    cv2.rectangle(frame, (x,y), (x+w, y+h), (0,255,0), 2)
    """
    frame: 이미지 또는 비디오 프레임을 나타내는 변수입니다.
    (x, y): 사각형의 왼쪽 위 모서리의 좌표입니다.
    (x + w, y + h): 사각형의 오른쪽 아래 모서리의 좌표입니다. 여기서 w는 사각형의 너비, h는 사각형의 높이입니다.
    (0, 255, 0): 사각형의 선 색상을 나타내는 RGB 값입니다. (R, G, B) 형식으로 표현됩니다. 여기서 (0, 255, 0)은 녹색을 나타냅니다.
    2: 사각형 선의 두께를 나타냅니다.
    """
    

    # 화면에 출력
    cv2.imshow("backproj", backproj)
    cv2.imshow("frame", frame)

    # 'q'를 누르면 종료
    if cv2.waitKey(60) == ord('q'):
        exit()

# 해제
cap.release()
cv2.destroyAllWindows()

 

import cv2

# 평균 이동 추적을 위한 초기 사각형 설정
track_window = None  # 객체의 위치 정보 저장할 변수
roi_hist = None  # 히스토그램을 저장할 변수
trem_crit = (cv2.TERM_CRITERIA_EPS|cv2.TERM_CRITERIA_COUNT, 10,1)  # 반복횟수 10

# 영상 파일 열기 
cap = cv2.VideoCapture("MS/데이터전처리/0612/data/slow_traffic_small.mp4")

# 첫 프레임에서 추적할 객체 선택
ret, frame = cap.read()
x, y, w, h = cv2.selectROI("selectROI", frame, False, False)
print("선택한 박스의 좌표 >>", x, y, w, h)


# 추적할 객체 초기 히스토그램 계산
roi = frame[y:y+h, x:x+w]
hsv_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV) # (Hue, Saturation, Value)
roi_hist = cv2.calcHist([hsv_roi], [0], None, [180], [0,180]) # 히스토그램 계산
cv2.normalize(roi_hist, roi_hist, 0, 255, cv2.NORM_MINMAX) # 히스토그램을 0부터 255로 정규화 (정확도 높일려고)

# 추적할 객체의 초기 윈도우 설정 
track_window = (x, y, w, h)
# cv2.imshow("roi test", roi)
# cv2.waitKey(0)

# 평균 이동 추적
while True:
    # 프레임 읽기
    ret, frame = cap.read()
    if not ret:
        break

    # 추적할 객체에 대한 채도 히스토그램 역투영계산
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    backproj = cv2.calcBackProject([hsv], [0], roi_hist, [0,180], 1)

    # 평균 이동으로 새 위치 검색
    ret, track_window = cv2.meanShift(backproj, track_window, trem_crit)

    # 검색된 새 위치에 사각형 그리기
    x, y, w, h = track_window
    print("새 위치 좌표 >>", x, y, w, h)
    cv2.rectangle(frame, (x,y), (x+w, y+h), (0,0,255), 2)

    # 화면에 출력
    cv2.imshow("backproj", backproj)
    cv2.imshow("frame", frame)

    # 'q'를 누르면 종료
    if cv2.waitKey(60) == ord('q'):
        break

# 해제
cap.release()
cv2.destroyAllWindows()

 

 

 

https://webnautes.tistory.com/1257

 

OpenCV Python 강좌 - 모폴로지 연산 (Morphological Operations)

OpenCV에서 제공하는 Erosion, Dilation, Opening, Closing 연산하는 함수들을 다룹니다. 보통 바이너리 이미지(Binary Image)에서 흰색으로 표현된 오브젝트의 형태를 개선하기 위해 사용됩니다. 마지막 업데

webnautes.tistory.com

을 먼저보고오는게 이해가 더 잘됨

1.  threshold 

경계면 구분을 원활하게 진행함

 

import cv2
import matplotlib.pyplot as plt
import numpy as np

image_path= "./data/a.png"

image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
"""
230보다 큰 값은 모두 255로 설정되고 작은값은 0으로 (흰색으로 바뀜)
"""

_, mask = cv2.threshold(image, 230, 255, cv2.THRESH_BINARY_INV)

image_list = np.hstack([
    image,
    mask
])

plt.imshow(image_list, 'gray')
plt.show()

 

 

 

2. 확장 침식 실험 - 02

import cv2
import matplotlib.pyplot as plt
import numpy as np

image_path= "./data/a.png"

image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
_, mask = cv2.threshold(image, 230, 255, cv2.THRESH_BINARY_INV)

                        
kernel = np.ones((3,3), np.uint8)
dilation = cv2.dilate(mask, kernel, iterations=2) # iterations 반복횟수
erosion = cv2.erode(mask, kernel)                     

image_list = np.hstack([
    image,
    mask,
    dilation,  # 팽창
    erosion   # 침식
])

plt.imshow(image_list, 'gray')
plt.title('org img to mask, dilation, erosion')
plt.show()

 

 

image_path= "./data/a.png"

image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
_, mask = cv2.threshold(image, 230, 255, cv2.THRESH_BINARY_INV)

                        
kernel = np.ones((3,3), np.uint8)
dilation = cv2.dilate(mask, kernel, iterations=2) # iterations 반복횟수
erosion = cv2.erode(mask, kernel)
opening = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
closing = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)

image_list = np.hstack([
    image,
    mask,
    dilation, 
    erosion,  
    opening,  
    closing
])

plt.imshow(image_list, 'gray')
plt.title('org img to mask, dilation, erosion, opening, closing')
plt.show()

 

3. 확장 침식 실험 - 03

 

image_path= "./data/a.png"

image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
_, mask = cv2.threshold(image, 230, 255, cv2.THRESH_BINARY_INV)

                        
kernel = np.ones((3,3), np.uint8)
dilation = cv2.dilate(mask, kernel, iterations=2) # iterations 반복횟수
erosion = cv2.erode(mask, kernel)
opening = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
closing = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)

mg = cv2.morphologyEx(mask, cv2.MORPH_GRADIENT, kernel)   # 팽창과 침식의 차  / 경계, 윤곽선, 테두리 등을 추출에 주로 쓰임
th = cv2.morphologyEx(mask, cv2.MORPH_TOPHAT, kernel)     #                 이미지의 밝은 영역에서 뚜렷한 경계를 강조

image_list = np.hstack([
    image,
    mask,
    dilation, 
    erosion,  
    opening,  
    closing
])

image_list_01 = np.hstack([
    mg,
    th
])

plt.imshow(image_list, 'gray')
plt.title('org img to mask, dilation, erosion, opening, closing')
plt.show()

plt.imshow(image_list_01, 'gray')
plt.title('org img to mg, th')
plt.show()

 

1.  커스텀 필터로 data폴더안에 있는 모든 .png파일 불러오기

import cv2
import matplotlib.pyplot as plt
import numpy as np
import os
import glob


image_path = "./data"
image_list = glob.glob(os.path.join(image_path, "*.png"))  # data 폴더안에 .png를 모두 불러옴

for path in image_list :
    print(path)
    image = cv2.imread(path, 1)
    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    
    # custom filter 
    filter = np.array([[3,-2, -2 ], [-3, 7, -5], [5, -1, 0]])
    
    """
    각각의 a, b, c는 필터의 가중치  값을 나타냅니다. 이 값은 이미지의 각 픽셀과 이웃한 픽셀 간의 계산에 사용됩니다. 
    필터는 이미지의 각 픽셀에 적용되며, 
    필터 윈도우 내의 픽셀 값과 필터의 가중치를 곱한 후 합산합니다.
    """
    
    # custom filter 적용 
    custom_filter_img = cv2.filter2D(image, -1, filter)  # -1 : 출력이미지의 뎁스를 입력이미지와 동일하게
    
    plt.imshow(custom_filter_img)
    plt.show()

2.  세피아 필터적용

image_path = "./data"
image_list = glob.glob(os.path.join(image_path, "*.png"))

for path in image_list :
    print(path)
    image = cv2.imread(path, 1)
    
    # 효과필터 적용
    filter_ = np.array([[0.272, 0.534, 0.131], [0.119,0.686, 0.168], [0.393, 0.769, 0.189]])
    sepia_img = cv2.transform(image, filter_)
    
    plt.imshow(sepia_img)
    plt.show()
    
    
    """
    cv2.transform 함수는 이미지의 전체적인 변환 작업에 사용되며, 
    cv2.filter2D 함수는 이미지 필터링 작업을 통해 픽셀 값을 변형하는 데 사용됩니다.
    """

 

 

3. 엠보스효과

 

import cv2
import matplotlib.pyplot as plt
import numpy as np
import os
import glob

image_path = "./data"
image_list = glob.glob(os.path.join(image_path, "*.png"))

for path in image_list :
    print(path)
    image = cv2.imread(path, 1)
    
    # 엠보스 효과
    filter_temp = np.array([[0, 1, 0], [0, 0, 0], [0, -1, 0]])
    
    emboss_img = cv2.filter2D(image, -1, filter_temp)
    emboss_img = emboss_img + 128
    
    plt.imshow(emboss_img)
    plt.show()

학습을 시키기위해 이미지 데이터를 1차원 벡터로 변환하는  과정

 

import cv2
import matplotlib.pyplot as plt

image_path = "./data/box.png"

### 경계선 찾기
# 1. 픽셀 강도의 중간값을 계산
image_gray = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)

image_10x10 = cv2.resize(image_gray, (10,10)) # image 10x10 픽셀 크기로 변환 
image_10x10.flatten()  # 이미지 데이터를 1차원 벡터로 변환

plt.imshow(image_10x10, 'gray')
plt.show()

 

 

#### 머신러닝 특성 컬러 이미지 처리 결과


image_color = cv2.imread("./data/iamge01.png")
image_color = cv2.cvtColor(image_color, cv2.COLOR_BGR2RGB)

# image size 10 x 10
image_10x10_temp = cv2.resize(image_color, (10,10)) # image 10x10 픽셀 크기로 변환 
a = image_10x10_temp.flatten() # 이미지 데이터를 1차원 백터로 변환
print(a, a.shape)

# image size 100 x 100
image_100x100_temp = cv2.resize(image_color, (100,100)) # image 10x10 픽셀 크기로 변환 
b = image_255x255_temp.flatten() # 이미지 데이터를 1차원 백터로 변환


plt.imshow(image_10x10_temp)
plt.show()

plt.imshow(image_100x100_temp)
plt.show()

 

 

1. 이미지회전 

- cv2.rotate() 함수활용

- 옵션(이미지, cv2.ROTATE_{각도}_(COUNTER)CLOCKWISE)

import cv2
import matplotlib.pyplot as plt
import numpy as np

image_path = "./data/cat.png"
image = cv2.imread(image_path)

# RGB 타입으로 변경 
image_org_ = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

# 이미지 회전
image_90 = cv2.rotate(image_org_, cv2.ROTATE_90_CLOCKWISE)
image_180 = cv2.rotate(image_org_, cv2.ROTATE_180)
image_270 = cv2.rotate(image_org_, cv2.ROTATE_90_COUNTERCLOCKWISE)

plt.imshow(image_90)
plt.show()

plt.imshow(image_180)
plt.show()

plt.imshow(image_270)
plt.show()

 

2. 상하좌우 반전 

- cv2.flip()

- cv2.flip(이미지, 1 or 0)  1은 좌우반전, 0은 상하반전

 

import cv2
import matplotlib.pyplot as plt
import numpy as np

image_path = "./data/cat.png"
image = cv2.imread(image_path)

# RGB 타입으로 변경 
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

# 1은 좌우 반전 / 0번은 상하 반전
dst_1 = cv2.flip(image, 1)
dst_2 = cv2.flip(image, 0)

plt.imshow(dst_1)
plt.show()

plt.imshow(dst_2)
plt.show()

1. 블러처리 (이미지블러, 가우시안블러)

1. 이미지블러 cv2.blur() 함수활용

import cv2
import matplotlib.pyplot as plt

image_path = "./data/cat.png"
image = cv2.imread(image_path)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

image_blurry = cv2.blur(image, (5,5)) # cv2.blur() 를 활용함
# 33 55 77   # 블러강도를 나타냄  

plt.imshow(image)
plt.show()

plt.imshow(image_blurry)
plt.show()

 

 

2. 가우시안블러 cv2.Gaussianblur() 함수활용 

이걸 더 많이씀

import cv2
import matplotlib.pyplot as plt
import numpy as np

image_path = "./data/cat.png"
image = cv2.imread(image_path)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

image_g = cv2.GaussianBlur(image, (9,9), 0)   # cv2.GaussianBlur() 를 사용함  
# (9,9): 주변 커널수-> 세기조절이 됨
# 0 : 표준편차

plt.imshow(image)
plt.show()

plt.imshow(image_g)
plt.show()

 

 

 

 

2. 이미지 선명하게하기

import cv2
import matplotlib.pyplot as plt
import numpy as np

image_path = "./data/cat.png"
image = cv2.imread(image_path)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

kernel_ = np.array([[0,-1,0],
                    [-1,5,-1],
                    [0,-1,0]
                   ])

image_sharp = cv2.filter2D(image, -1, kernel_)

plt.imshow(image)
plt.show()

plt.imshow(image_sharp)
plt.show()

 

3. 이미지 대비높이기

1 . 그레이스케일 일때  : 히스토그램 평활화 cv2.equalizeHist()에 BGR2Gray 활용 : 

import cv2
import matplotlib.pyplot as plt
import numpy as np

image_path = "./data/cat.png"
image = cv2.imread(image_path)
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 단일 이미지에서만 적용가능!
image_enhanced = cv2.equalizeHist(image_gray)

plt.imshow(image_gray, 'gray')
plt.show()

plt.imshow(image_enhanced, 'gray')
plt.show()

 

2. 컬러일때 : RGB에 YUV를 추가함

import cv2
import matplotlib.pyplot as plt
import numpy as np

image_path = "./data/cat.png"
image = cv2.imread(image_path)

# RGB 타입으로 변경 
image_org = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

# YUV 타입으로 변경 
image_yuv = cv2.cvtColor(image, cv2.COLOR_BGR2YUV)

# 히스토그램 평활화 적용 
image_yuv[:,:,0] = cv2.equalizeHist(image_yuv[:,:,0])

# YUV > RGB 
image_rgb = cv2.cvtColor(image_yuv , cv2.COLOR_YUV2RGB)


plt.imshow(image_yuv)
plt.show()

plt.imshow(image_org)
plt.show()

plt.imshow(image_rgb)
plt.show()

4. 이진화(흑백)

 

import cv2
import matplotlib.pyplot as plt
import numpy as np

image_path = "./data/cat.png"
image = cv2.imread(image_path)

image_gray_01 = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 이미지 이진화 
max_output_value = 255 
neighborhood_size = 99
subtract_from_mean = 10
image_binarized = cv2.adaptiveThreshold(
                                image_gray_01,
                                max_output_value,
                                cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
                                cv2.THRESH_BINARY, # cv2.THRESH_BINARY_INV(반전)
                                neighborhood_size,
                                subtract_from_mean
)

plt.imshow(image_binarized, 'gray')
plt.show()

1.  이미지 타입, 크기 확인하기

import cv2
image_path = "./data/cat.png"

# image read 
image = cv2.imread(image_path)

# image 타입 
image_type = type(image)
print("이미지 타입 >> " , image_type)

# 이미지 크기 확인 
image_height, image_width, image_channel = image.shape
print(image_height, image_width, image_channel)

# 이미지 타입 >>  <class 'numpy.ndarray'>
# 162 310 3

 

2. 이미지 리사이징

import cv2
import matplotlib.pyplot as plt

image_path = "./data/cat.png"

image = cv2.imread(image_path)

image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)  # cv2로 불러오면  BGR을 RGB로 바꿔줘야함
# https://itcreator.tistory.com/141 에 적어둠

# 이미지 크기 조절 
image_resize = cv2.resize(image, (244,244))

# 이미지 크기 확인 
image_height_, image_width_, _ = image_resize.shape


# 원본 이미지 
plt.imshow(image)
plt.show()

 

# 리사이즈 이미지 
print(image_height_, image_width_)
# 244 244

plt.imshow(image_resize)
plt.show()

# 저장하기

import cv2
image_resize = cv2.cvtColor(image_resize, cv2.COLOR_BGR2RGB)  
cv2.imwrite("./data/resize_image.png", image_resize)  # cv2.imwrite로 저장하기

# True라고 뜨면 저장된거

 

3. 이미지 자르기(슬라이싱)

import cv2
import matplotlib.pyplot as plt

image_path = "./data/cat.png"
image = cv2.imread(image_path)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

image_cropped = image[10:,:200]   #  [행시작:행끝, 열시작:열끝]

plt.imshow(image)
plt.show()

 

plt.imshow(image_cropped)
plt.show()

 

 

3-1. 이미지자르기(좌표)

import cv2
import matplotlib.pyplot as plt

image_path = "./data/cat.png"
image = cv2.imread(image_path)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)


x1, y1 = 50, 50 # 좌측 상단 모서리 좌표 
x2, y2 = 150,150 # 우측 하단 모서리 좌표 

cropped_image_test = image[y1:y2, x1:x2]   # y가 먼저인 이유는 좌표평면에서 행렬의 행은 y값임
plt.imshow(cropped_image_test)
plt.show()

 

 

 

 

 

 

2. 변환하기

3. 리사이즈

4. 크롭  (슬라이싱,좌표)

 

1.  이미지 불러오기 (png파일)

# !pip install opencv-python==4.5.5.64
import cv2
from matplotlib import pyplot as plt 


img = cv2.imread("./data/cat.png")    # cv2 라이브러리의 imread() 함수로 불러옴

# 색상의 문제 발생 -> BGR -> RGB 
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

plt.imshow(img)
plt.show()

2. 이미지 저장하기(.npy)

넘파이를 이용하여 배열로 저장하기

.npy 파일로 저장하는 방법

import numpy as np
np.save("./data/image.npy", img)  #  현재위치에 있는 data 폴더에 image.npy로 이미지만들기


# 만약에 해당폴더가 없으면 폴더생성하는 파이썬 코드
import os

def createDirectory(directory):
    try:
        if not os.path.exists(directory):
            os.makedirs(directory)
    except OSError:
        print("Error: Failed to create the directory.")

2-1. 이미지 저장하기(PIL)

PIL은 간단한 이미지 처리와 변환 작업에 사용하기 좋음 / 컴퓨터 비전 작업에서는 OpenCV를 쓰는게 맞음

#!pip install Pillow
import numpy as np
from PIL import Image

# 이미지 불러오기 
img = Image.open("./data/cat.png").convert('L') # 그레이 스케일 변환
print(img)

img_array = np.array(img)

np.save("./data/pil_image.npy", img_array)  # .npy로 저장
img_array1 = np.load("./data/pil_image.npy")  # .npy 불러오기

# 다시 PIL 이미지로 변환 
img = Image.fromarray(np.uint8(img_array1))    # pil의 Image라이브러리 fromarray()로 변환
img.save("./data/image_numpy.png")            # pil로 png로 변환       


org_size = os.path.getsize("./data/cat.png")
np_save_size = os.path.getsize("./data/pil_image.npy")
pil_save_size = os.path.getsize("./data/image_numpy.png")

# 용량차이 확인하기 
print(org_size, "bytes")
print(np_save_size, "bytes")
print(pil_save_size, "bytes")


# 원본 : 6468 bytes
# .npy로 저장 : 50348 bytes   
# PIL를 활용하여 png로 저장 26808 bytes

 

3. 이미지 불러오기 (.npy)

img_data = np.load("./data/image.npy")  # 넘파이의 load()로 불러옴

plt.imshow(img_data)
plt.show()

 

 

메타에서 SAM(Segment Anything Model)이라는 모델을 무려 오픈소스(Apache-2.0 license) 공개하였습니다. 이미지 개체를 인식하여 영역을 분할하는 모델로 기존 대비 훨씬 많은 데이터로 학습하여 뛰어난 성능을 보여줍니다.

 

SAM 소개 페이지

https://segment-anything.com/ https://ai.facebook.com/blog/segment-anything-foundation-model-image-segmentation

 

 

SAM 깃허브  

https://github.com/facebookresearch/segment-anything

 

 

SAM 데모 써보기

https://segment-anything.com/demo

https://paperswithcode.com/trends

- 나도코딩 OpenCV @ https://bit.ly/3AyaDB1
- OpenCV 공식 튜토리얼 (Basics + ObjectDetection & PoseEstimation, 3h) @ https://j.mp/3xlNxKX
- Hand tracking / Gesture volume control / AI Trainer using CPU @ https://j.mp/32L77mU & https://j.mp/3wWGUif
- Python OpenCV4로 배우는 CV & ML (CNN/DNN/SVM/KNN 포함) @ http://j.mp/2WRedpa
- OpenCV 튜토리얼 (유튜브 3h, 문서스캔/차량번호판탐지 포함) @ https://j.mp/39mvKuw
- OpenCV FreeCodeCamp (유튜브 3h, 얼굴탐지/심슨캐릭터분류 포함) @ https://j.mp/2LyqWZy
- 영상처리 OpenCV 강의 @ https://goo.gl/PxfXj3
- [dlib & opencv 기반 프로젝트] 얼굴인식 @ https://j.mp/2JVSzan / 성별&나이인식 @ https://j.mp/2JVSzan / 눈깜빡임 감지 @ https://j.mp/3c91Ub2
- Face detection 예시코드 & 성능비교 (Opencv/dlib/mtcnn/S3FD/retinaface) @ https://j.mp/2FuTFLX
- YOLO v5 커스텀 학습 (빵형) @ https://bit.ly/3Hq8eKv

RGB 대신 BGR을 쓰는 이유

1: 사진, 영상에서는 당연히 RGB 순서로 사용하는데 CV에서는 왜 BGR을 사용할까?

 

구글링을 했더니  사타야 말릭 박사(Dr. Satya Mallick) 의 글을 찾을 수 있었습니다. 
본문을 요약하면 사타야 말릭 박사는 한 컨퍼런스에서 OpenCV의 창시자인 그레이 브라드스키 박사(Dr. Gray Bradski)를 만났고 그에게 왜 RGB가 아닌 BGR을 쓰냐고 물었고 그에 대한 대답은 “왜 미국 철도 표준이 4피트 8.5 인치 인가?”라는 질문으로 되돌아 왔다고 합니다. 
이게 무슨 말이냐면 미국이 철도 표준을 정할때 무슨 대단한 이유가 있어서 4피트 8.5인치로 정한것이 아니라 열차 이전에 주로 사용했던 마차의 폭에 마춰서 정했다는 겁니다. 결국, 브라드스키 박사도 BGR로 정한데는 별다른 이유가 있던게 아니라 그걸 정하던 시절 초창기 카메라 산업 개발자들이 BGR을 많이 썼기 때문에 그 자신도 그냥 아무 생각없이 BGR을 선택했다는 거죠.
 

2: 그럼 왜  영상 기기 개발자들 사이에서는 RGB보다 BGR을 많이 사용했을까?

 
이는 엔디안(Endianness)와 관련이 있습니다.
CPU에 따라서 값을 메모리에 저장하고 읽을 때,  MSB 즉 큰 값을 먼저 쓰는 빅엔디안과 LSB 즉 작은 값을 먼저 쓰는 리틀엔디언 방식이 있는데, 인텔에서 만든 x86계열의 CPU는 리틀엔디언을 따릅니다.
(OpenCV는 인텔에서 시작)
 
예를 들어 0x123456이라는 값을 빅엔디언으로 저장하면 0x123456 순으로 저장되지만 리틀엔디언으로 저장하면 0x563412순으로 저장되게 됩니다.
BGR 포맷으로 이루어진 색상 정보는 각 채널당 8비트로 이루어 지고 3개의 채널을 사용하므로 24비트 즉, 0xBBGGRR가 필요합니다.  24비트 단위의 입출력은 효과적이지 않으니 메모리에 저장할때 unsigned 32비트를 사용하는것이 일반적인데 이렇게 되면 0x00BBGGRR 가 됩니다. 이 값을 x86 계열의 CPU 처럼 리틀엔디언을 사용해서 저장하면 메로리에는  0xRRGGBB00가 저장됩니다.

 

이렇게 저장된 값을 메모리에 직접 접근해서 읽어 들이는 디스플레이 장치, 카메라 등의 영상 하드웨어에서는 CPU와 무관하게 지정된 엔디안으로 앞에서 부터 읽어 들이면 자연스럽게 RGB로 읽히기 때문에 BGR 포맷이 초창기 영상 기기 관련 하드웨어 개발자들에게 자연스레 널리 사용되었다고 볼 수 있습니다.
BGR 포맷과 엔디안과의 관계에 대한 추가적인 의견은 아래의 스택오버플로우 링크에서도 보 실 수 있습니다.
 

+ Recent posts