두번째 예제에 있던 오타 및 오류를 잡았습니다.
테스트에 사용한 이미지입니다.
openCV 3.0부터 라벨링 알고리즘이 추가되었습니다.. 이미지를 라벨링하고 원하는 라벨을 색으로 표현한다든가.. 각각의 영역들을 박스치는 것등이 쉽게되네요.. 해당 영역의 크기도 각각 계산되서 나옵니다.. 자세한건 아래 소스코드를 읽어 보세요...
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | #include <iostream> #include <opencv2/core/mat.hpp> #include <opencv2/imgcodecs.hpp> #include <opencv2/imgproc.hpp> #include <opencv2/highgui.hpp> using namespace cv; using namespace std; int main() { Mat img_gray, img_color, img_binary; img_gray = imread("art8.jpg", IMREAD_GRAYSCALE ); threshold(img_gray, img_binary, 127, 255, THRESH_BINARY); cvtColor( img_gray, img_color, COLOR_GRAY2BGR ); Mat img_labels,stats, centroids; int numOfLables = connectedComponentsWithStats(img_binary, img_labels, stats, centroids, 8,CV_32S); //라벨링된 이미지중 특정 라벨을 컬러로 표현해주기 for ( int y=0; y<img_labels.rows; ++y ) { int *label = img_labels.ptr<int>(y); Vec3b* pixel = img_color.ptr<Vec3b>(y); for (int x = 0; x < img_labels.cols; ++x) { if (label[x] == 3 ) { pixel[x][2] = 0; pixel[x][1] = 255; pixel[x][0] = 0; } } } //라벨링 된 이미지에 각각 직사각형으로 둘러싸기 for (int j = 1; j < numOfLables; j++) { int area = stats.at<int>(j, CC_STAT_AREA); int left = stats.at<int>(j, CC_STAT_LEFT); int top = stats.at<int>(j, CC_STAT_TOP); int width = stats.at<int>(j, CC_STAT_WIDTH); int height = stats.at<int>(j, CC_STAT_HEIGHT); rectangle( img_color, Point(left,top), Point(left+width,top+height), Scalar(0,0,255),1 ); putText(img_color, to_string(j), Point(left+20,top+20), FONT_HERSHEY_SIMPLEX, 1, Scalar(255,0,0), 2); } imshow( "result", img_color ); waitKey(0); } | cs |
centroids를 이용하여 라벨링 된 영역의 중심을 출력해보았습니다..
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | #include <iostream> #include <opencv2/core/mat.hpp> #include <opencv2/imgcodecs.hpp> #include <opencv2/imgproc.hpp> #include <opencv2/highgui.hpp> using namespace cv; using namespace std; int main() { Mat img_gray, img_color, img_binary; img_gray = imread("1.png", IMREAD_GRAYSCALE); threshold(img_gray, img_binary, 127, 255, THRESH_BINARY); cvtColor(img_gray, img_color, COLOR_GRAY2BGR); Mat img_labels, stats, centroids; int numOfLables = connectedComponentsWithStats(img_binary, img_labels, stats, centroids, 8, CV_32S); //라벨링된 이미지중 특정 라벨을 컬러로 표현해주기 for (int y = 0; y<img_labels.rows; ++y) { int *label = img_labels.ptr<int>(y); Vec3b* pixel = img_color.ptr<Vec3b>(y); for (int x = 0; x < img_labels.cols; ++x) { if (label[x] == 3) { pixel[x][2] = 0; pixel[x][1] = 255; pixel[x][0] = 0; } } } //라벨링 된 이미지에 각각 직사각형으로 둘러싸기 for (int j = 1; j < numOfLables; j++) { int area = stats.at<int>(j, CC_STAT_AREA); int left = stats.at<int>(j, CC_STAT_LEFT); int top = stats.at<int>(j, CC_STAT_TOP); int width = stats.at<int>(j, CC_STAT_WIDTH); int height = stats.at<int>(j, CC_STAT_HEIGHT); int x = centroids.at<double>(j, 0); //중심좌표 int y = centroids.at<double>(j, 1); circle(img_color, Point(x, y), 5, Scalar(255, 0, 0), 1); rectangle(img_color, Point(left, top), Point(left + width, top + height), Scalar(0, 0, 255), 1); putText(img_color, to_string(j), Point(left + 20, top + 20), FONT_HERSHEY_SIMPLEX, 1, Scalar(255, 0, 0), 2); } imshow("result", img_color); waitKey(0); } | cs |
'OpenCV > OpenCV 강좌' 카테고리의 다른 글
Opencv 3.1 + Qt 5 프로그래밍 예제 (0) | 2016.05.29 |
---|---|
RANSAC을 이용한 Line fitting (0) | 2016.05.27 |
opencv를 이용하여 wxPython에서 웹캠 영상 띄우기 (0) | 2016.05.23 |
openCV 라벨링 예제 ( connectedComponentsWithStats ) (65) | 2015.11.19 |
opencv 튜토리얼 - hough line transform (3) | 2015.11.16 |
opencv python - Harris Corner Detection (2) | 2015.11.13 |
opencv python - K-Means Clustering (3) | 2015.11.10 |
opencv python - 극좌표를 이용하여 방사형으로 라인 그리기 (0) | 2015.11.07 |
포스트 작성시에는 문제 없었지만 이후 문제가 생길 수 있습니다.
개선 사항을 댓글로 남겨주면 가능한 빨리 반영하도록 하겠습니다.
여러분의 응원으로 좋은 컨텐츠가 만들어집니다.
지금 본 내용이 도움이 되었다면 유튜브 구독 부탁드립니다.
감사합니다 ~~
유튜브 구독하기
제가 쓴 책도 한번 검토해보세요 ^^
- 이전 댓글 더보기
-
안녕하세요
마커 인식해서 ar 구현중인데
minAreaRect함수로 잡영제거 마커영역을 추출하려고 합니다.
이거 참고해서
http://docs.opencv.org/3.0-rc1/de/d62/tutorial_bounding_rotated_ellipses.html
vector<RotatedRect> minRect(numOfLables);
minRect[1] = minAreaRect(img_labels.getMat(1));
이렇게 하면 될것 같은데 잘안되네요
vector<RotatedRect> minRect(numOfLables);
minRect[1] = minAreaRect(img_labels[1]);
이것도 안되고요
int left = stats.at<int>(j, CC_STAT_LEFT);
int top = stats.at<int>(j, CC_STAT_TOP);
int width = stats.at<int>(j, CC_STAT_WIDTH);
int height = stats.at<int>(j, CC_STAT_HEIGHT);
을 사용해서 하면 사각형이 기울어져서 마른모가 된경우가 잘안될것 같아서요..
-
답변감사합니다.
라벨링을 마커인식에 사용해 보려고 하는데
딱 흰색바람개비부분만 Mat로 추출 어떻게 하면 될까요?
imshow( "바람개비1", img_바람개비1 ); 이런식으로 출력가능하게요 -
휴일인데도 답변감사합니다.
Mat sub_image= img(roi).clone();
이렇게 하면 사각형 영역이 다들어 오는데
혹시 딱 흰색바람개비부분만 추출할수 없나 해서요... -
조조 2016.09.29 16:04
중심좌표를 구하고 싶어서 소스를 그대로 써보았는데
double *centroid = ¢roids.at<double>(j, 0);
위코드에서 에러가 납니다.
"¢roids" 이게 무엇을 뜻하는건가요????????? -
-
-
화연 2017.02.10 11:38
//라벨링된 이미지중 특정 라벨을 컬러로 표현해주기
for (int y = 0; y<img_labels.rows; ++y) {
int *label = img_labels.ptr<int>(y);
Vec3b* pixel = img_color.ptr<Vec3b>(y);
for (int x = 0; x < img_labels.cols; ++x) {
if (label[x] == 3) {
pixel[x][2] = 0;
pixel[x][1] = 255;
pixel[x][0] = 0;
}
}
}
해당 문에서 x 관련 for 문에서 특정 부분가면 에러가 나네요. 배열을 벗어나서 그런거같은데 해결을 못하겠네요.
처음쓰는 3.0 함수라 ㄷㄷ 혹시 확인해주실수 있으신가요? -
영상처리 2017.06.08 16:44
안녕하세요 본 게시물을 잘보고있습니다! 본코드에서 잡음이 라벨링이되서 그러는데
라벨링의 최소범위를 정할수있을까요?
-
-
라벨링 처리한 후, 영역별로 다음 6가지 정보를 Mat 객체에 저장한 겁니다.
CC_STAT_LEFT
라벨링 영역의 가장 왼쪽 좌표
(라벨 영역을 둘러싸는 박스의 왼쪽 포인트 좌표가 됩니다.)
CC_STAT_TOP
라벨링 영역의 가장 위쪽 좌표
(라벨 영역을 둘러싸는 박스의 위쪽 포인트 좌표가 됩니다.)
CC_STAT_WIDTH
라벨 영역을 둘러싸는 박스의 너비
CC_STAT_HEIGHT
라벨 영역을 둘러싸는 박스의 높이
CC_STAT_AREA
라벨 영역의 크기(픽셀 개수)
CC_STAT_MAX
가장 큰 영역의 라벨
http://docs.opencv.org/3.2.0/d3/dc0/group__imgproc__shape.html#gac7099124c0390051c6970a987e7dc5c5
-
-
kimsj 2017.08.22 14:47
안녕하세요! opencv에서 라벨링 관련한 예제를 찾고 있었는데 정말 많이 도움이 되었어요! 감사합니다 :)
한가지 여쭤보고 싶은게 있는데요,
저는 색을 추출해서 제가 추적할 공을 라벨링하는 것을 구현하고 싶은데,
area를 사용해서 가장 크기가 큰 것을 표시하려고 했더니
area가 라벨링 하나 하나의 넓이가 아니고 전체 넓이의 합이라서
제가 설정한 범위가 넘으면 라벨링이 여러 개가 그대로 표시가 되더라구요!
혹시 가장 크기가 큰 라벨링 하나를 표시하려고 하면 어떻게 해야할까요..?
CC_STAT_MAX 를 사용하는 건가요..?
http://docs.opencv.org/3.2.0/d3/dc0/group__imgproc__shape.html#gac7099124c0390051c6970a987e7dc5c5
여기에도 CC_STAT_MAX에 관한 설명이 없어서 잘 모르겠어요.. 허허 알려주시면 정말 정말 감사하겠습니다!
좋은 자료 올려주셔서 감사합니다 수고하세요 :) -
label 2017.09.25 17:20
특정라벨에 색깔넣어주신 코드가 있는데
왜 3번 라벨에 색이 들어간건가요? 어떤점이 특정한거에요?? 라벨링 공부중이라 ㅠㅠ -
-
god 2017.09.27 17:02
안녕하세요 제가
https://m.blog.naver.com/PostView.nhn?blogId=tramper2&logNo=100062623403&proxyReferer=https%3A%2F%2Fwww.google.co.kr%2F
위 사이트에서 이진화, 라벨링, 엣지 검출하는 오픈소스를 어떤분이 올려주셔서 해보았는데...
이진화까진 모든게 이해가 가는데 라벨링에서 int값을 주는데 그 int값이 하는 역할이 뭔가요??
라벨링은 그냥 이미지값에 대해서 처음부터 끝까지 쭉 훑으면서 백이냐, 흑이냐만따지면 되는거 아닌가요..
ㅠㅠ 라벨링 너무 어렵네요-
gd 2017.09.28 13:28
오픈소스에서는
private void Labeling(int iSetLabel)
이렇게 라벨링 함수에 int값을 인자로 넣어주고
// 라벨치에 의한 화상을 뽑아내
for (i = 0; i < pictureBox1.Image.Width; i++)
for (j = 0; j < pictureBox1.Image.Height; j++)
// 설정한 라벨의 경우
if (iArrayValue[i, j] == iSetLabel)
bBitmap.SetPixel(i, j, Color.White); // 백색으로 설정
// 설정한 라벨 이외의 경우
else
bBitmap.SetPixel(i, j, Color.Black); // 흑색으로 설정
pictureBox1.Image = bBitmap; // 변경 결과 출력
if문에서 쓰이거든요. 근데 int값 크기에 따라서 뭐가 달라지는지를 잘 모르겠어요 ㅠㅠ
말씀하신 픽셀에 대응하는 2차원배열에 넣어주는건 또 무슨말인지...
라벨링에 대해서 너무이해가 안가네요 죄송합니다 ㅠㅠ -
라벨링을 하려면 별도의 이미지 크기의
배열이 하나 필요합니다.
예를 들어 이미지에 공이 5개 있다면..
이미제에서 각 공에 속하는 픽셀에 대응하는 배열의 위치에는 각각 고유의 번호가 부여됩니다.
그래서 결과적으로 배경에 대응하는 영역에는 모두 0값을 가지게 되고 각 공에 대응하는 영역에는 각각 1~5 사이의 값을 가지게 됩니다.
코드 일부라 확실치 않지만..
언급하신 코드에서는 이미 원하는 영역의 라벨 번호를 아는 상태라고 가정한듯합니다.
그래서 해당 번호(코드에서는 INT 타입의 값)이면 해당 영역만 흰색으로 해서 화면에 보여주고 나머지는 검은색으로 처리한겁니다.
-
kevin 2018.05.24 00:18
잘 보고 있습니다!!
근데 디버그시 오류가 있어서요
imshow( "result", img_color ); 이 줄에서
'처리되지 않은 예외 발생(0x00007FFC7589F218, Project1.exe): Microsoft C++ 예외: cv::Exception, 메모리 위치 0x000000D6722FE800.'
라는 에러가 나는데 어떻게 처리해야하는지 아시나요? -
-
-
watchwatch 2019.03.14 14:42
안녕하세요! 잘 보고있어요!! 웹캠에서 라벨링을 진행하려고 위 코드를 참고하고 있는데 감이 안잡혀서요,,, 도움 부탁드립니다!
-
ㅁㅁㅁㅁ 2019.05.04 14:28
for (int y = 0; y<img_labels.rows; ++y) {
int *label = img_labels.ptr<int>(y);
Vec3b* pixel = img_color.ptr<Vec3b>(y);
Vec3b*pixel 2= img_binary.ptr<Vec3b>(y);
for (int x = 0; x < img_labels.cols; ++x) {
if (label[x] == 3) {
pixel[x][2] = 0;
pixel[x][1] = 255;
pixel[x][0] = 0;
}
if(label[x] ==3){
pixel2[x][2] = 0;
pixel2[x][1] =0;
pixel2[x][0] = 0;
}
}
이런식으로 해서 바이너리 이미지의 값을 바꾸고 싶은데 좌표가 다르게 바뀝니다.
바이너리 이미지는 크기가 다른 것인가요?
크기를 같게 설정하려면 어떻게 해야하나요? -
12213 2019.05.08 23:51
위에 질문에 답변은 잘 받았습니다. 하나만 더 여쭤보고 싶습니다. ㅠ
Mat img_labels, stats, centroids;
int numOfLables = connectedComponentsWithStats(img_mask1, img_labels,
stats, centroids, 8, CV_32S);
int left = stats.at<int>(idx, CC_STAT_LEFT);
int top = stats.at<int>(idx, CC_STAT_TOP);
int width = stats.at<int>(idx, CC_STAT_WIDTH);
int height = stats.at<int>(idx, CC_STAT_HEIGHT);
이를 통해서 X,Y 좌표값을 받았고,
이 좌표 값을이용해 사각형 내부를 흰색 (255,255,255)의 값으로 모두 변경 하려고 하였습니다.
for (int j = top; j < (top + height); j++)
{
for (int i = left; i < (left + width); i++)
{
img_mask1.at<Vec3b>(j, i)[0] = 255;
img_mask1.at<Vec3b>(j, i)[1] = 255;
img_mask1.at<Vec3b>(j, i)[2] = 255;
}
}
이런 방식으로 하였는데 에러가 나서 그런데 어떤 것이 잘못 되었을까요?-
코드에 뭔가 빠진 상태 같아서 어디서 에러인지 알기 힘듭니다..
포스트에 있는 다음 코드처럼 작성하면 됩니다.
Mat img_labels, stats, centroids;
int numOfLables = connectedComponentsWithStats(img_binary, img_labels,
stats, centroids, 8, CV_32S);
//라벨링된 이미지중 특정 라벨을 컬러로 표현해주기
for (int y = 0; y<img_labels.rows; ++y) {
int *label = img_labels.ptr<int>(y);
Vec3b* pixel = img_color.ptr<Vec3b>(y);
for (int x = 0; x < img_labels.cols; ++x) {
if (label[x] == 3) {
pixel[x][2] = 0;
pixel[x][1] = 255;
pixel[x][0] = 0;
}
}
}