아래의 공유 기술 그레이 스케일 이미지에서 선분을 찾으려면 cv::HoughLinesP()
을 사용하십시오.
입력 이미지를 그레이 스케일로로드하여 응용 프로그램을 시작합니다. 이 시점에서 시각화하는 파일에 기록 될 수있는 검출 된 모든 선분
#include <cv.h>
#include <highgui.h>
#include <algorithm>
// Custom sort method adapted from: http://stackoverflow.com/a/328959/176769
// This is used later by std::sort()
struct sort_by_y_coord
{
bool operator()(cv::Vec4i const& a, cv::Vec4i const& b) const
{
if (a[1] < b[1]) return true;
if (a[1] > b[1]) return false;
return false;
}
};
int main()
{
/* Load input image as grayscale */
cv::Mat src = cv::imread("13531682.jpg", 0);
/* Pre-process the image to enhance the characteristics we are interested at */
medianBlur(src, src, 5);
int erosion_size = 2;
cv::Mat element = cv::getStructuringElement(cv::MORPH_CROSS,
cv::Size(2 * erosion_size + 1, 2 * erosion_size + 1),
cv::Point(erosion_size, erosion_size));
cv::erode(src, src, element);
cv::dilate(src, src, element);
/* Identify all the lines in the image */
cv::Size size = src.size();
std::vector<cv::Vec4i> total_lines;
cv::HoughLinesP(src, total_lines, 1, CV_PI/180, 100, size.width/2.f, 20);
int n_lines = total_lines.size();
std::cout << "* Total lines: "<< n_lines << std::endl;
cv::Mat disp_lines(size, CV_8UC1, cv::Scalar(0, 0, 0));
// For debugging purposes, the block below writes all the lines into disp_lines
// for (unsigned i = 0; i < n_lines; ++i)
// {
// cv::line(disp_lines,
// cv::Point(total_lines[i][0], total_lines[i][2]),
// cv::Point(total_lines[i][3], total_lines[i][4]),
// cv::Scalar(255, 0 ,0));
// }
// cv::imwrite("total_lines.png", disp_lines);
: 그럼 cv::HoughLinesP()
의한 검출을 개선하는 것을 목표로, 이미지의 특정 특성을 향상시키는 기본적인 전처리 동작을 수행 목적 :
우리가
cv::HoughLinesP()
가 그렇게하지 않기 때문에 라인의 우리의 벡터를 분류하기 위해 필요한이 시점에서
, 우리는 벡터가 측정하고 비교함으로써, 라인 그룹을 식별 할 수 분류 필요 줄 사이의 거리 :
/* Sort lines according to their Y coordinate.
The line closest to Y == 0 is at the first position of the vector.
*/
sort(total_lines.begin(), total_lines.end(), sort_by_y_coord());
/* Separate them according to their (visible) groups */
// Figure out the number of groups by distance between lines
std::vector<int> idx_of_groups; // stores the index position where a new group starts
idx_of_groups.push_back(0); // the first line indicates the start of the first group
// The loop jumps over the first line, since it was already added as a group
int y_dist = 35; // the next groups are identified by a minimum of 35 pixels of distance
for (unsigned i = 1; i < n_lines; i++)
{
if ((total_lines[i][5] - total_lines[i-1][6]) >= y_dist)
{
// current index marks the position of a new group
idx_of_groups.push_back(i);
std::cout << "* New group located at line #"<< i << std::endl;
}
}
int n_groups = idx_of_groups.size();
std::cout << "* Total groups identified: "<< n_groups << std::endl;
단순히 새로운 vector<int>
에서 라인의 벡터의 인덱스 위치를 저장하는 위의 코드의 마지막 부분은 그래서 우리는 새로운 그룹을 시작하는 줄 알고있다.
예를 들어, 새 벡터에 저장된 인덱스는 0 4 8 12
이라고 가정합니다. 기억하십시오 : 그들은 각 그룹의 시작을 정의합니다. 즉, 그룹의 결말은 0, 4-1, 4, 8-1, 8, 12-1, 12
입니다. 그것을 알고
, 우리는 다음과 같은 코드 쓰기 :
/* Mark the beginning and end of each group */
for (unsigned i = 0; i < n_groups; i++)
{
// To do this, we discard the X coordinates of the 2 points from the line,
// so we can draw a line from X=0 to X=size.width
// beginning
cv::line(disp_lines,
cv::Point(0, total_lines[ idx_of_groups[i] ][7]),
cv::Point(size.width, total_lines[ idx_of_groups[i] ][8]),
cv::Scalar(255, 0 ,0));
// end
if (i != n_groups-1)
{
cv::line(disp_lines,
cv::Point(0, total_lines[ idx_of_groups[i+1]-1 ][9]),
cv::Point(size.width, total_lines[ idx_of_groups[i+1]-1 ][10]),
cv::Scalar(255, 0 ,0));
}
}
// mark the end position of the last group (not done by the loop above)
cv::line(disp_lines,
cv::Point(0, total_lines[n_lines-1][11]),
cv::Point(size.width, total_lines[n_lines-1][12]),
cv::Scalar(255, 0 ,0));
/* Save the output image and display it on the screen */
cv::imwrite("groups.png", disp_lines);
cv::imshow("groove", disp_lines);
cv::waitKey(0);
cv::destroyWindow("groove");
return 0;
}
을 그리고 결과 이미지는 다음과 같습니다
그것은 완벽하게 일치은 아니지만, 가까이. 여기저기서 약간의 조정으로이 접근법이 훨씬 향상 될 수 있습니다.나는 sort_by_y_coord
에 대한 더 똑똑한 논리를 작성함으로써 시작할 것인데, 이는 X 좌표 (즉, 작은 선분)와 X 축에 완벽하게 정렬되지 않은 선들 사이의 거리가 작은 선 (예 : 두 번째 그룹의 선 출력 이미지에서). 이 제안은 응용 프로그램에서 생성 된 첫 번째 이미지를 평가하는 데 시간을 할애하면 훨씬 더 의미가 있습니다.
행운을 빈다.
샘플 이미지를 포함 할 수 있습니까? –
Stackoverflow에 오신 것을 환영합니다. 신중하게 내 대답을 검토 한 다음 도움이된다면 투표하십시오. 질문 옆에있는 확인란을 클릭하여 질문에 대한 공식 답변으로 선택할 수 있습니다. 이런 것들을함으로써 당신은이 스레드를 조직화하여 미래의 방문자들을 돕고 자신과 우리를 도울 것입니다. – karlphillip