Opencv 연결 영역 중심 인 스 턴 스 구하 기
절 차 는 다음 과 같다.
1)적합 한 한도 값 이치 화
2)윤곽 구하 기
3)계산 중심
otsu 알고리즘 최 적 한도 값 구하 기
otsu 법(최대 클래스 간 분산 법,때로는 대진 알고리즘 이 라 고도 함)은 집합 사상 을 사용 하여 이미지 의 그 레이스 케 일 수 를 그 레이스 케 일 등급 에 따라 2 개 부분 으로 나 누 어 두 부분 간 의 그 레이스 케 일 차이 가 가장 크 고 각 부분 간 의 그 레이스 케 일 차이 가 가장 적 으 며 분산 계산 을 통 해 적당 한 그 레이스 케 일 등급 을 찾 아 구분 합 니 다.otsu 알고리즘 은 이미지 분할 에서 한도 값 을 선택 하 는 가장 좋 은 알고리즘 으로 계산 이 간단 하고 이미지 밝기 와 대비 도의 영향 을 받 지 않 습 니 다.따라서 클래스 간 의 방 차 가 가장 큰 분할 은 오 분 확률 이 가장 적 다 는 것 을 의미한다.
계산 윤곽
opencv 에서 함수 findContours 함수
findContours(이치 화 이미지,윤곽,hierarchy,윤곽 검색 모드,윤곽 유사 방법,offset)
그 레이스 케 일 중심 법
그 레이스 케 일 중심 법 으로 중심 을 계산 하고 그 레이스 케 일 중심 법 은 지역 내 모든 픽 셀 위치 에 있 는 그 레이스 케 일 값 을 이 점 의'질량'으로 하 며 지역 중심 을 구 하 는 공식 은 다음 과 같다.
그 중에서 f(u,v)는 좌표 가(u,v)인 픽 셀 점 의 그 레이스 케 일 값 으로 목표 구역 의 집합 이 고 지역 중심 좌표 이 며 그 레이스 케 일 중심 법 은 지역 의 에너지 중심 을 추출 합 니 다.
//otsu
int Otsu(Mat &image)
{
int width = image.cols;
int height = image.rows;
int x = 0, y = 0;
int pixelCount[256];
float pixelPro[256];
int i, j, pixelSum = width * height, threshold = 0;
uchar* data = (uchar*)image.data;
//
for (i = 0; i < 256; i++)
{
pixelCount[i] = 0;
pixelPro[i] = 0;
}
//
for (i = y; i < height; i++)
{
for (j = x; j<width; j++)
{
pixelCount[data[i * image.step + j]]++;
}
}
//
for (i = 0; i < 256; i++)
{
pixelPro[i] = (float)(pixelCount[i]) / (float)(pixelSum);
}
// ostu ,
// [0,255], ,
float w0, w1, u0tmp, u1tmp, u0, u1, u, deltaTmp, deltaMax = 0;
for (i = 0; i < 256; i++)
{
w0 = w1 = u0tmp = u1tmp = u0 = u1 = u = deltaTmp = 0;
for (j = 0; j < 256; j++)
{
if (j <= i) //
{
// i ,
w0 += pixelPro[j];
u0tmp += j * pixelPro[j];
}
else //
{
// i ,
w1 += pixelPro[j];
u1tmp += j * pixelPro[j];
}
}
u0 = u0tmp / w0; //
u1 = u1tmp / w1; //
u = u0tmp + u1tmp; //
//
deltaTmp = w0 * (u0 - u)*(u0 - u) + w1 * (u1 - u)*(u1 - u);
//
if (deltaTmp > deltaMax)
{
deltaMax = deltaTmp;
threshold = i;
}
}
// ;
return threshold;
}
int main()
{
Mat White=imread("white.tif");//
int threshold_white = otsu(White);// , otsu
cout << " :" << threshold_white << endl;
Mat thresholded = Mat::zeros(White.size(), White.type());
threshold(White, thresholded, threshold_white, 255, CV_THRESH_BINARY);//
vector<vector<Point>>contours;
vector<Vec4i>hierarchy;
findContours(thresholded, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);//
int i = 0;
int count = 0;
Point pt[10];//
Moments moment;//
vector<Point>Center;//
for (; i >= 0; i = hierarchy[i][0])//
{
Mat temp(contours.at(i));
Scalar color(0, 0, 255);
moment = moments(temp, false);
if (moment.m00 != 0)// 0
{
pt[i].x = cvRound(moment.m10 / moment.m00);//
pt[i].y = cvRound(moment.m01 / moment.m00);//
}
Point p = Point(pt[i].x, pt[i].y);//
circle(White, p, 1, color, 1, 8);//
count++;//
Center.push_back(p);// Center
}
}
cout << " :" << Center.size() << endl;
cout << " :" << contours.size() << endl;
imwrite("Center.tif", White);
}
원본 그림:이치 화:
중심 점:
보충 지식:opencv 템 플 릿 패키지 에 따라 한도 값 화 된 윤곽 조합
이미지 처리 에서 특징 과 배경의 대비 도가 높 아야 하 는 동시에 적당 한 이미지 분할 도 문 제 를 해결 하 는 관건 이다.
블 로 거들 의 이전 방법 은 기본 적 인 것 이 특징 이 고 반드시 가장 큰 연결 역 이 어야 하기 때문에 한도 값 화 된 후에 윤곽 을 찾 아 면적 이 가장 큰 윤곽 을 직접 추출 하면 된다.
그러나 다른 상황 이 존재 할 수 있 습 니 다.아무리 한도 값 화 와 팽창 이 있어 도 원 하 는 특징 은 여러 조각 으로 나 뉘 어 져 있 습 니 다.즉,끊 어 집 니 다.이때 예측 할 수 없 는 간섭 과 소음 을 더 하면 findcontours 이후 많은 윤곽 을 얻 을 수 있 습 니 다.
그러면 문제 가 생 겼 습 니 다.우리 가 필요 로 하 는 것 은 어떤 윤곽 입 니까?아니면 몇 개의 윤곽 이 조 합 된 구역 입 니까?
본문의 의미 도 여기에 있다.
템 플 릿 의 볼록 가방 에 따라 그림 에서 가장 비슷 한 윤곽 조합 을 구 합 니 다.
이 방법 은 주로 matchspes 함 수 를 사용 하고 이러한 전 제 를 바탕 으로 한다.템 플 릿 패키지 의 2/3 부분 은 템 플 릿 패키지 와 의 싱크로 율 이 템 플 릿 패키지 의 1/2 부분 보다 크다.
말 이 많 지 않 으 니 코드 를 달 아 라.
void getAlikeContours(std::vector<cv::Point> Inputlist, cv::Mat InputImage, std::vector<cv::Point> &Outputlist)
{
Mat image;
InputImage.copyTo(image);
vector<vector<Point> > contours;
findContours(image, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);//
for (int idx = contours.size() - 1; idx >= 0; idx--)
{
for (int i = contours[idx].size() - 1; i >= 0; i--)
{
if (contours[idx][i].x == 1 || contours[idx][i].y == 1 || contours[idx][i].x == image.cols - 2 || contours[idx][i].y == image.rows - 2)
{
swap(contours[idx][i], contours[idx][contours[idx].size() - 1]);
contours[idx].pop_back();
}
}
// ,
for (int idx = contours.size() - 1; idx >= 0; idx--)
{
if (contours[idx].size() == 0) contours.erase(contours.begin() + idx);
}
while (true)
{
if (contours.size() == 0) break;
if (contours.size() == 1)
{
vector<Point> finalList;
finalList.assign(contours[0].begin(), contours[0].end());
convexHull(Mat(finalList), Outputlist, true);
break;
}
int maxContourIdx = 0;
int maxContourPtNum = 0;
for (int index = contours.size() - 1; index >= 0; index--)
{
if (contours[index].size() > maxContourPtNum)
{
maxContourPtNum = contours[index].size();
maxContourIdx = index;
}
}
//
int secondContourIdx = 0;
int secondContourPtNum = 0;
for (int index = contours.size() - 1; index >= 0; index--)
{
if (index == maxContourIdx) continue;
if (contours[index].size() > secondContourPtNum)
{
secondContourPtNum = contours[index].size();
secondContourIdx = index;
}
}
vector<Point> maxlist;
vector<Point> maxAndseclist;
vector<Point> maxlistHull;
vector<Point> maxAndseclistHull;
maxlist.insert(maxlist.end(), contours[maxContourIdx].begin(), contours[maxContourIdx].end());
maxAndseclist.insert(maxAndseclist.end(), contours[maxContourIdx].begin(), contours[maxContourIdx].end());
maxAndseclist.insert(maxAndseclist.end(), contours[secondContourIdx].begin(), contours[secondContourIdx].end());
convexHull(Mat(maxlist), maxlistHull, true);
convexHull(Mat(maxAndseclist), maxAndseclistHull, true);
double maxcontourScore = matchShapes(Inputlist, maxlistHull, CV_CONTOURS_MATCH_I1, 0);
double maxandseccontourScore = matchShapes(Inputlist, maxAndseclistHull, CV_CONTOURS_MATCH_I1, 0);
if (maxcontourScore>maxandseccontourScore)
{
contours[maxContourIdx].insert(contours[maxContourIdx].end(), contours[secondContourIdx].begin(), contours[secondContourIdx].end());
}
contours.erase(contours.begin() + secondContourIdx);
}
}
이상 의 Opencv 에서 연결 구역 의 중심 인 스 턴 스 를 구 하 는 것 은 바로 편집장 이 여러분 에 게 공유 하 는 모든 내용 입 니 다.여러분 께 참고 가 되 고 여러분 들 이 저 희 를 많이 지지 해 주시 기 바 랍 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Opencv 연결 영역 중심 인 스 턴 스 구하 기otsu 법(최대 클래스 간 분산 법,때로는 대진 알고리즘 이 라 고도 함)은 집합 사상 을 사용 하여 이미지 의 그 레이스 케 일 수 를 그 레이스 케 일 등급 에 따라 2 개 부분 으로 나 누 어 두 부분 간 의...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.