Tekniğin temeli Aşağıdaki paylaşımda bulunmaktayım, gri tonlamalı bir görüntüdeki çizgi parçalarını bulmak için cv::HoughLinesP()
kullanır.
Uygulama giriş görüntüsünü gri tonlamalı olarak yükleyerek başlar. Bu noktada, görüntüleme için bir dosyaya yazılır algılanan tüm çizgi parçaları
#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);
: Sonra cv::HoughLinesP()
tarafından gerçekleştirilen algılama geliştirmek amacıyla, görüntünün belli özelliklerini geliştirmek için temel bir ön-işleme işlemi gerçekleştirir amaçları:

biz
cv::HoughLinesP()
bunu yapmaz çünkü çizgilerin bizim vektör sıralamak gerekir Bu noktada
ve biz vektör ölçerek ve kıyaslayarak, çizgilerin gruplarını tanımlamak edebilmek için tasnif gerek satırlar arasındaki mesafe:
/* 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;
sadece yeni vector<int>
satır vektörü endeks pozisyonlarını saklar Yukarıdaki kod son kısmı bu yüzden yeni bir grup başladığı çizgiler biliyorum. Örneğin, yeni vektörte saklanan dizinlerin: 0 4 8 12
olduğunu varsayalım. Unutmayın: Her bir grubun başlangıç numarasını tanımlarlar. Yani, grupların bitiş çizgileri: 0, 4-1, 4, 8-1, 8, 12-1, 12
. bilerek
, aşağıdaki kodu yazmak:
/* 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;
}
Ve çıkan resimdir:

Mükemmel bir maç değil, ama yakın. Burada biraz tweaks ile bu yaklaşım çok daha iyi olabilir.Ben sort_by_y_coord
için daha akıllı bir mantık yazarak başlayacağım, bu X koordinatları (yani küçük çizgi parçaları) arasında küçük mesafeler olan satırları ve aynı zamanda X ekseninde mükemmel hizalanmayan satırları (ikinci gruptaki gibi) içermeyen satırları atmalıdır çıktı görüntüsünde). Bu öneri, uygulama tarafından oluşturulan ilk resmi değerlendirmek için zaman ayırdıktan sonra çok daha anlamlı hale gelir.
İyi şanslar.
Örnek bir resim ekleyebilir misiniz? –
Stackoverflow'a Hoş Geldiniz. Lütfen cevabımı dikkatle gözden geçirin, sonra size yardımcı olursa oy verin. Sorunuzun resmî cevabı olarak seçmek için yakınındaki onay kutusunu tıklayabilirsiniz. Bu işi yaparak, bu iş parçacığını organize ederek kendiniz ve bizim gibi gelecekteki ziyaretçilere yardımcı olacaksınız. – karlphillip