| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 |
- Gaussian
- sensor
- Binary
- parameter
- Class
- Gradient
- Read
- atmega328
- edge
- digitalRead
- Encapusulation
- public
- flutter
- subpixel
- wpf
- SERIAL
- UNO
- memory
- aduino
- stream
- compare
- Filtering
- file access
- c++
- Android
- mfc
- Pointer
- APP
- Unity
- Contour
- Today
- Total
폴크(FOLC)
알고리즘 - Edge 추출 방법 ( Optimally Oriented Flux ) 본문
OOF는 국소적인 미분 연산의 한계를 넘어, 영역 기반의 에너지 흐름을 분석함으로써 복잡하고 밀집된 구조물에서 가장 신뢰할 수 있는 선 추출이 가능하다.
목적: 이미지에서 가늘고 길게 이어진 구조를 검출
적용 분야: 혈관, 신경 섬유, 기관지, 섬유 패턴 분석 등
핵심 아이디어:
- 픽셀 주변의 Hessian 행렬(2차 미분) 분석 + 인접 구조물의 간섭 활용
- 고유값 패턴으로 선형성 판단의 약점을 보완하고자 개발됨
장점
- 인접 구조 간섭에 강함
- 방향 정보 추출 가능
- scale 추정이 가능
- 분석적 계산 가능
한계
- 반지름 범위 설정이 중요
- 노이즈에 완전히 자유롭지 못함
- 분기점과 고곡률 구조는 후처리가 필요함.
소스 코드
// C++14 / OpenCV 4.x
#include <opencv2/opencv.hpp>
#include <algorithm>
#include <vector>
#include <cmath>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <complex>
using namespace cv;
using namespace std;
// OOF 필터 함수
void applyOOF(const Mat& src, Mat& response, float radius) {
Mat gray;
if (src.channels() == 3) cvtColor(src, gray, COLOR_BGR2GRAY);
else gray = src.clone();
// 1. 입력을 float 형으로 변환 및 FFT를 위한 패딩
Mat floatSrc;
gray.convertTo(floatSrc, CV_32F, 1.0 / 255.0);
int m = getOptimalDFTSize(floatSrc.rows);
int n = getOptimalDFTSize(floatSrc.cols);
Mat padded;
copyMakeBorder(floatSrc, padded, 0, m - floatSrc.rows, 0, n - floatSrc.cols, BORDER_CONSTANT, Scalar::all(0));
// 2. FFT 수행
Mat planes[] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)};
Mat complexI;
merge(planes, 2, complexI);
dft(complexI, complexI);
// 3. 주파수 도메인에서 OOF 필터(Bessel 기반) 생성 및 적용
// OOF 커널: 1/r * (sin(r*w) / w - cos(r*w)) 형태의 근사치 사용
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
float u = (i > m / 2) ? (float)i - m : (float)i;
float v = (j > n / 2) ? (float)j - n : (float)j;
float w = sqrt(u * u + v * v);
if (w > 0) {
// 주파수 영역에서의 OOF 가중치 계산
float filterValue = (sin(radius * w) / (radius * w) - cos(radius * w)) / (w * w);
complexI.at<Vec2f>(i, j)[0] *= filterValue;
complexI.at<Vec2f>(i, j)[1] *= filterValue;
}
}
}
// 4. 역 FFT (Inverse DFT)
idft(complexI, complexI);
split(complexI, planes);
// 5. 결과 후처리 (고유값 분석 대용으로 크기 계산)
magnitude(planes[0], planes[1], response);
response = response(Rect(0, 0, gray.cols, gray.rows));
normalize(response, response, 0, 255, NORM_MINMAX, CV_8U);
}
#include <opencv2/opencv.hpp>
int main() {
cv::Mat gray = cv::imread("input.png", cv::IMREAD_GRAYSCALE);
cv::Mat oofResult;
applyOOF(gray, oofResult, 5.f);
// 보기 좋게 0~255로 변환해 저장
cv::Mat vis; oofResult.convertTo(vis, CV_8U, 255.0);
cv::imwrite(" oofResult.png", vis);
return 0;
}
'머신 비전 > 머신 비전 알고리즘 테크닉 CPP' 카테고리의 다른 글
| 머신 비전 알고리즘 - OpenCV - 이미지처리33 (0) | 2021.08.24 |
|---|---|
| 머신 비전 알고리즘 - OpenCV - 이미지처리32 (0) | 2021.08.24 |
| 머신 비전 알고리즘 - OpenCV - 이미지처리31 (0) | 2021.08.20 |
| 머신 비전 알고리즘 - OpenCV - 이미지처리30 (0) | 2021.08.15 |
| 머신 비전 알고리즘 - OpenCV - 이미지처리29 (0) | 2021.08.14 |