Mt.Hwang 2025. 6. 8. 12:15

* OpenCV

Open Source Computer Vision Library

컴퓨터 비전, 이미지 처리, 머신 작업을 위한 오픈소스 라이브러리

Python과 함께 많이 사용
C++, Java도 있음


주요 기능은
 1. 이미지 처리
 2. 객체 감지
 3. 얼굴 인식
 4. 영상 필터링
 5. 카메라 캡쳐
 6. 딥러닝 모델 활용


라이선스는 BSD 라이선스

..~~~~..

 * 스프링 부트에서 사용

 1. Gradle에서

dependencies {
    implementation 'org.openpnp:opencv:4.7.0-0'
}


 2. OpenCV 라이브러리 로딩

@PostConstruct
public void init() {
    System.loadLibrary(Core.NATIVE_LIBRARY_NAME);  // ex) opencv_java470
}

정확히는 라이브러리 초기화

@Configuration public class ExampleConig {} 이런데에 넣어놈
혹은 해당 기능을 사용하는 서비스 클래스에 넣어놓음

컨트롤러에는 안 넣는 것이 좋다

..~~~~..

 * 스프링 부트에서의 이미지 처리 흐름

 1. 클라이언트가 이미지 업로드
 2. MultipartFile -> OpenCV의 Mat 변환
 3. OpenCV 처리
 4. Mat -> byte[] 변환

..~~~~..

 * OpenCV 설치

 1. 터미널에서 Homebrew로 설치

brew install opencv


 2. OpenCV 라이브러리 경로 확인

brew info opencv

설치하면 opencv의 설치 경로는 보통
 1. /usr/local/opt/opencv
 2. /opt/homebrew/opt/opencv
둘 중 한 곳에 위치함

나 같은 경우는 /opt/homebrew/Cellar/opencv/4.11.0_1

 
 3. 네이티브 라이브러리 경로 확인

ls /opt/homebrew/Cellar/opencv/4.11.0_1/share/java/
ls /opt/homebrew/Cellar/opencv/4.11.0_1/lib/

나 같은 경우는 /opt/homebrew/Cellar/opencv/4.11.0_1/lib/


 4. OpenCV 소스코드 직접 설치

의존 설치
brew install cmake ant openjdk

OpenCV 소스 다운로드
git clone https://github.com/opencv/opencv.git
cd opencv
git checkout 4.11.0  // 자기가 설치한 버전 맞춰서

빌드 디렉토리 설치
mkdir build && cd build

CMake 설정
cmake -D CMAKE_BUILD_TYPE=Release \
      -D CMAKE_INSTALL_PREFIX=/opt/homebrew/opt/opencv-custom \
      -D BUILD_SHARED_LIBS=ON \
      -D BUILD_opencv_java=ON \
      -D ANT_EXECUTABLE=/opt/homebrew/bin/ant \
      -D JAVA_HOME=$(/usr/libexec/java_home) \
      ..

빌드 및 설치
make -j8
make install


 5. 스프링부트, OpenCV 바인딩

스프링부트 프로젝트에 OpenCV jar 포함하기
프로젝트 폴더에 mkdir libs
cp /opt/homebrew/Cellar/opencv/4.11.0_1/lib/opencv/build/bin/opencv-4110.jar libs/
cp /opt/homebrew/Cellar/opencv/4.11.0_1/lib/opencv/build/lib/libopencv_java4110.dylib libs/

build.gradle에 의존성 추가
dependencies {
    implementation files('libs/opencv-4110.jar')
}

네이티브 라이브러리 위치 지정하기
 1. 터미널에서 JVM 옵션 설정 : java -Djava.library.path=/opt/homebrew/Cellar/opencv/4.11.0_1/lib/opencv/build/lib -jar your-app.jar
 2. 스프링 부트에서 JVM 옵션 설정 : -Djava.library.path=/opt/homebrew/Cellar/opencv/4.11.0_1/lib/opencv/build/lib
 3. 로컬에서 쓸 때 : -Djava.library.path=libs

1, 2는 배포 서버에서 쓰면 좋고, 3은 로컬에서 쓸 때 사용

Tesseract와 함께 써서
-Djna.library.path=/opt/homebrew/opt/tesseract/lib:/opt/homebrew/Cellar/opencv/4.11.0_1/lib/opencv/build/lib
-Djava.library.path=/opt/homebrew/Cellar/opencv/4.11.0_1/lib/opencv/build/lib
이렇게 입력했음

코드 내에서 OpenCV 네이티브 라이브러리 로드


네이티브 라이브러리 파일 위치는 보통
 1. /opt/homebrew/Cellar/opencv/4.7.0/share/java/
 2. /opt/homebrew/Cellar/opencv/4.7.0/lib/
둘 중 한 곳에 위치함


Java 내에서의 바인딩은
System.loadLibrary(Core.NATIVE_LIBRARY_NAME); // 보통 "opencv_javaXXX"

Java의 native lib path에 있는 .so, .dylib, .dll 파일을 로드
.jar만 복사하면 안 되고, 위의 .so(Linux), .dylib(Mac), .dll(Windows) 경로도 있어야 함


JVM 옵션인 -Djava.library.path= 는 꼭 설정해야된다.
Spring Boot에서 실행할 때는 application.properties에서 설정 가능

..~~~~..

 * OpenCV API

OpenCV API는 클래스 기반 static 함수 구조이기 때문에 다음과 같은 형식의 사용 가능

이미지 읽기
 1. Imgcodecs.imread()
 2. imdecode()

이미지 저장
 1. Imgcodecs.imwrite()
 2. imencode()

색상 변환
 1. Imgproc.cvtColor()

블러링
 1. Imgproc.GaussianBlur()

에지 검출
 1. Imgproc.Canny()

윤곽선 검출
 1. Imgproc.findContours(0

이진화 처리
 1. Imgproc.threshold()

..~~~~..

 * OpenCV 클래스

 Mat 클래스
이미지를 저장하는 핵심 클래스
행렬 (Matrix) 구조로 이미지 데이터 저장

empty() -> boolean : 비어있는 이미지인지 확인

size() -> Size : 이미지 크기 반환

channels() -> int : 채널 수 반환 (RGB인 경우 3)

clone() -> Mat : 현재 이미지의 복사본 생성

release() -> void : 메모리 해제

put(int row, int col, byte ... data) -> void : 특정 위치에 픽셀 값 저장

get(int row, int col) -> double [] : 특정 위치의 픽셀 값 반환


 Imgcodecs 클래스
이미지 입출력을 담당하는 클래스

imread(String filename) -> Mat : 파일로부터 이미지 읽기

imread(String filename, int flags) -> Mat : 색상 옵션 지정해서 이미지 읽기

imwrite(String filename, Mat image) -> boolean : 이미지를 파일로 저장

imencode(String ext, Mat image, MatOfBytebuf) -> 이미지를 메모리 버퍼로 인코딩

imdecode(Mat buf, int flags) -> Mat : 메모리 버퍼에서 이미지 디코딩


 Imgproc 클래스 :
이미지 전처리 및 변환 담당 클래스

cvtColor(Mat src, Mat dst, int code) -> void : 색상 변환 (예를 들어 RGB -> GRAY)

GaussianBlur(Mat src, Mat dst, Size ksize, double sigmaX) -> void : 가우시안 블러링

Canny(Mat src, Mat edges, double threshold1, double threshold2) -> void : 윤곽선 검출

threshold(Mat src, Mat dst, double thresh, double maxval, int type) -> double : 이진화 작업. 임계값을 반환함

findContours(Mat images, List<MatOfPoint> contours, Mat hierachy, int mode, int method) -> void : 윤곽선 검출

resize(Mat src, Mat dst, Size size) -> void : 이미지 크기 조절


 Core 클래스 :
행렬 연산, 기초 연산, 비트 연산 담당

add(Mat src1, Mat src2, Mat dst) -> void : 두 행렬의 합

bitwise_not(Mat src, Mat dst) -> void : 비트 반전. NOT 연산

bitwise_and(Mat src1, Mat src2, Mat dst) -> void : AND 연산

bitwise_or(Mat src1, Mat src2, Mat dst) -> void : OR 연산

..~~~~..

 * 관련 용어

 그레이 스케일 (Grayscale) : 
컬러 이미지를 흑백 이지미로 변환하는 것

불필요한 색상 정보를 제거함으로써 계산량 줄임
많은 알고리즘이 밝기 기반이기 때문에 전처리가 필수


 블러 처리 (Blurring, Gaussian Blur) : 
이미지를 흐릿하게 만들어서 노이즈나 세세한 정보를 줄이는 작업

노이즈를 제거함으로써 추후의 에지 검출 같은 작업의 정확도 향상
너무 세세한 정보(잡음)는 무시하고 전체적인 윤곽에 집중 가능


 에지 검출 (Edge Detection, Canny) :
이미지에서 윤곽선 (경계)를 찾아내는 것
색상 또는 밝기 변화가 큰 부분을 경계로 인식


 캘리브레이션 (Calibration) :
값을 알고 있는 표준을 사용하여 측정 장치의 정밀도를 확인하고 조절하는 행위

..~~~~..

 * 기타 사항

서버 배포 시 native 라이브러리도 함께 배포해야 됨
(.so, .dll, .dylib)

System.loadLibrary 경로 문제 해결을 위해 -Djava.library.path 옵션 사용


OCR을 위한 Tesseract 연동은

Mat preprocessed = yourOpenCVProcessing(inputImage);
String ocrResult = tesseract.doOCR(preprocessedImageFile);


서버 환경에서 네이티브 라이브러리를 쓰는 방법은 대표적으로

System.loadLibrary(Core.NATIVE_LIBRARY_NAME);


웹 응답을 위해서 BufferedImage와의 변환이 필요하다
MultipartFile -> OpenCV Mat -> BufferedImage

..~~~~..