2015-11-17 16 views
5

Używam opencv_contrib do wykrywania regionów tekstowych na obrazie.Łączenie zachodzących na siebie grup na obrazku

Jest to obraz

Jest to obraz po występują obszary tekstowe oryginalny:

Jak widać, istnieją grupy nakładających się na obrazie. Na przykład, nie wydają się być dwie grupy wokół Hello World i dwa wokół Some more sample text

Pytanie W scenariuszach, takich jak te w jaki sposób mogę utrzymać możliwie najszersze pole poprzez połączenie dwóch pól. W przypadku tych przykładów zaczynały się od H, a kończąc na d, tak aby obejmowały Hello World. Moim powodem do zrobienia jest to, że chciałbym przyciąć część tego obrazu i wysłać go do tesseract.

Oto odpowiedni kod, który rysuje pola.

void groups_draw(Mat &src, vector<Rect> &groups) 
{ 
    for (int i=(int)groups.size()-1; i>=0; i--) 
    { 
     if (src.type() == CV_8UC3) 
      rectangle(src,groups.at(i).tl(),groups.at(i).br(),Scalar(0, 255, 255), 2, 8); 
    } 
} 

Oto, co próbowałem. Moje pomysły są w komentarzach.

void groups_draw(Mat &src, vector<Rect> &groups) 
{ 
    int previous_tl_x = 0; 
    int previous_tl_y = 0; 
    int prevoius_br_x = 0; 
    int previous_br_y = 0; 
    //sort the groups from lowest to largest. 
    for (int i=(int)groups.size()-1; i>=0; i--) 
    { 
     //if previous_tl_x is smaller than current_tl_x then keep the current one. 
     //if previous_br_x is smaller than current_br_x then keep the current one. 
     if (src.type() == CV_8UC3) { 
      //crop the image 
      Mat cropedImage = src(Rect(Point(groups.at(i).tl().x, groups.at(i).tl().y),Point(groups.at(i).br().x, groups.at(i).br().y))); 
      imshow("cropped",cropedImage); 
      waitKey(-1); 
     } 
    } 
} 

Aktualizacja

Próbuję użyć [groupRectangles][4] do osiągnięcia tego celu:

void groups_draw(Mat &src, vector<Rect> &groups) 
{ 
    vector<Rect> rects; 
    for (int i=(int)groups.size()-1; i>=0; i--) 
    { 
     rects.push_back(groups.at(i)); 
    } 
    groupRectangles(rects, 1, 0.2); 
} 

Jednak to daje mi błąd:

textdetection.cpp:106:5: error: use of undeclared identifier 'groupRectangles' 
    groupRectangles(rects, 1, 0.2); 
    ^
1 error generated. 
+0

Jakie jest twoje pytanie? – 1201ProgramAlarm

Odpowiedz

2

Po pierwsze, powód, dla którego nakładają się ramki ograniczające, polega na tym, że moduł wykrywający tekst działa na kanałach odwróconych (np. Szary i szary odwrócony), przez co wewnętrzne obszary niektórych znaków, takich jak o's i g, są nieprawidłowo wykrywane i pogrupowane jako znaki. Więc jeśli chcesz wykryć tylko jeden tryb tekstu (biały tekst na ciemnym tle), po prostu przepuść odwrócone kanały. Wymienić:

for (int c = 0; c < cn-1; c++) 
    channels.push_back(255-channels[c]); 

Z:

for (int c = 0; c < cn-1; c++) 
    channels[c] = (255-channels[c]); 

teraz na swoje pytanie, prostokąty zdefiniowano skrzyżowanie i łączenie operatorów:

rect = rect1 & rect2 (rectangle intersection) 
rect = rect1 | rect2 (minimum area rectangle containing rect2 and rect3) 
rect &= rect1, rect |= rect1 (and the corresponding augmenting operations) 

Można użyć tych operatorów podczas iteracji nad prostokątów w celu wykrycia przecinają się prostokąty i łączą je w następujący sposób:

if ((rect1 & rect2).area() != 0) 
    rect1 |= rect2; 

Edit:

pierwsze, rodzaj prostokąt grupach powierzchni od największej do najmniejszej:

std::sort(groups.begin(), groups.end(), 
      [](const cv::Rect &rect1, const cv::Rect &rect2) -> bool {return rect1.area() > rect2.area();}); 

Następnie iteracyjne nad prostokątów, kiedy dwa prostokąty przecinają dodać mniejszych do większych, a następnie usuń:

for (int i = 0; i < groups.size(); i++) 
     { 
      for (int j = i + 1; j < groups.size(); j++) 
      { 
       if ((groups[i] & groups[j]).area() != 0) 
       { 
        groups[i] |= groups[j]; 
        groups.erase(groups.begin() + j--);      
       } 
      } 
     } 
+0

Nie wiedziałem o odwróconych kanałach. Próbowałem tego, ale niektóre z moich obrazów mogą również zawierać czarny tekst na białym tle. Więc jestem zmuszony zachować to ustawienie tak, jak jest. Jeśli chodzi o łączenie przecinanych prostokątów, nie całkiem rozumiem, co masz na myśli. W twoim pseudo kodzie, skąd pochodzą 'rect1' i' rect2'? – Anthony

+0

Edytowałem odpowiedź i dodałem prawdziwy kod. – Baraa

+0

Natknąłem się na metodę groupRectangles w opencv http://docs.opencv.org/2.4/modules/objdetect/doc/cascade_classification.html?highlight=grouprect#cv2.groupRectangles Myślę, że będzie to bardziej efektywne w użyciu. Co myślisz? Próbuję przesunąć wszystkie prostokąty w 'grupach' do wektora, a następnie przekazać ten wektor do' groupRectangles'. Jednak pojawia się błąd 'error: użycie niezadeklarowanego identyfikatora 'groupRectangles''. Zaktualizowałem to pytanie za pomocą rozwiązania 'groupRectangles', które próbuję. – Anthony

0

Jedno podejście byłoby porównać każdy prostokąt z każdym innym prostokątem aby zobaczyć, czy nakładają się one na siebie lub przecinają. Jeśli robią to w wystarczającej ilości, możesz połączyć je w jeden większy prostokąt.

+0

Próbowałem zrobić coś takiego, ale nie mogłem sformalizować go w kodzie. .. – Anthony