2013-06-17 86 views
5

ảnh Input: enter image description herecụm Phát hiện các điểm ảnh màu trắng trong một hình ảnh sử dụng OpenCV

Dự kiến ​​Output: enter image description here

tôi dự định để phù hợp với ba (hoặc một số số) đa giác (đối với trường hợp này, hình chữ nhật) để biểu thị các đốm trắng "lớn" trong hình ảnh này. Các hình chữ nhật được vẽ trong hình ảnh đầu ra theo nhận thức của tôi về các vùng trắng. Tôi không mong đợi thuật toán để đưa ra các khu vực cùng một bó hoa. Những gì tôi muốn là để phù hợp với một số đa giác chặt chẽ xung quanh các cụm điểm ảnh màu trắng.

Giải pháp ban đầu của tôi bao gồm việc tìm đường viền cho hình ảnh này và lắp một đa giác lồi khép kín quanh mỗi đường bao bằng cách tìm thân lồi của các điểm trong mỗi đường bao. Tuy nhiên, vì các vùng màu trắng bị phân mảnh cao với các vùng màu đen bên trong và lẩn tránh xung quanh các cạnh, số lượng các đường bao trả về bởi cv2.findContours rất cao (khoảng 500 hoặc hơn). Do đó, việc lắp một thân lồi không cải thiện hình dạng của các vùng trắng. Các vùng trắng chủ yếu giữ lại hình dạng trừu tượng ban đầu của chúng. Mục tiêu của tôi là kết hợp nhiều đường nét nhỏ của một vùng trắng thành một đường bao quanh có chứa đường viền mà sau đó tôi có thể vừa vặn với một lồi lồi.

Làm cách nào để giải quyết vấn đề này? Tôi có nên sử dụng thuật toán phân cụm trên các điểm đường viền ban đầu để tìm các đường bao gần nhau không?

+0

http://en.wikipedia.org/wiki/DBSCAN có thể trợ giúp. dưới python scikit. demo tại đây http://scikit-learn.org/stable/auto_examples/cluster/plot_dbscan.html – baci

Trả lời

1

Bạn có thể sử dụng phân cụm km theo tọa độ x y làm đối tượng cho mỗi điểm trắng và ba cụm. Sau đó lấy vỏ lồi của ba cụm kết quả. Bạn có thể phải thử các điểm bắt đầu khác nhau và chọn kết quả tốt nhất. Xem http://docs.opencv.org/modules/core/doc/clustering.html#kmeans

2

Trước tiên bạn có thể làm giãn hình ảnh trước khi tìm đường nét. Sự giãn nở làm cho các vùng sáng sủa phát triển. Bạn có thể nghĩ về nó như là thêm các điểm ảnh màu trắng xung quanh tất cả các điểm ảnh màu trắng hiện có trong hình ảnh của bạn. Bằng cách này, các hình dạng sáng láng giềng được sáp nhập. Xem http://docs.opencv.org/doc/tutorials/imgproc/erosion_dilatation/erosion_dilatation.html

Bạn cũng có thể làm mờ và ngưỡng lại, nhưng làm mờ có thể tốn kém hơn nhiều so với giãn nở tùy thuộc vào lượng mờ.

3

Trước tiên, bạn cần thực hiện việc đóng hình thái học (đó là giãn nở theo sau là xói mòn) trên hình ảnh này. Điều này đóng tất cả các "lỗ nhỏ" mà hình ảnh của bạn có trong khi vẫn giữ được hình dạng và kích thước của các thành phần riêng lẻ. Trái ngược với nó, khi xói mòn được theo sau bởi sự giãn nở, nó loại bỏ các dấu chấm ồn ào trong hình ảnh. Tôi đang làm việc trên một hình ảnh tương tự và tôi đã phải thực hiện giãn nở + xói mòn nhiều đến 10 lần để thậm chí ra các thành phần của tôi. Sau khi bạn làm điều đó, hãy sử dụng các thành phần được kết nối hoặc tìm đường nét. Điều này chắc chắn sẽ làm giảm số lượng đường viền từ 400 đến 20-30.

Thứ hai, bạn đã đề cập bạn cần 3 cụm. Mặc dù hai cụm nhỏ (được bao phủ bởi đường màu đỏ) có thể đã hợp nhất thành một. Những gì tôi tạo ra từ đó là bạn muốn mỗi cụm của bạn được gắn chặt vào hình chữ nhật của nó càng tốt. Vì vậy, tôi sẽ đề nghị bạn thiết lập một hiệu quả ngưỡng (nói 80%) và sử dụng phân cụm phân cấp để hợp nhất từng thành phần được kết nối thành một cụm. Khi các pixel màu trắng của bạn tạo ra ít hơn 80% không gian của hình chữ nhật giới hạn của chúng (của một cụm), bạn sẽ ngừng phân cụm và nhận các cụm.

0

Bạn có thể vẽ đường bao xấp xỉ xung quanh hình dạng của mình cho đến khi bạn nhận được tất cả các vùng cần thiết được kết nối. Với điều này tôi đang làm xói mòn hình ảnh một cách hiệu quả. Nếu bạn vẽ một thân tàu quanh những vùng được kết nối đó, bạn sẽ nhận được hình chữ nhật màu đỏ của mình.

Chỉ cần lặp lại cho đến khi ba thân lớn nhất của bạn có một số tài sản cần thiết (ví dụ nếu họ bao gồm 99% của tất cả các chấm trắng)

#include <vector> 
using std::vector; 
#include <algorithm> 
using std::sort; 
#include <string> 
using std::string; 
using std::to_string; 
#include <iostream> 
using std::clog; 
using std::endl; 
#include <opencv2/opencv.hpp> 
using namespace cv; 

int main() 
{ 
    typedef vector<Point> Polygon; 
    typedef vector<Polygon> Polygons; 
    Mat mFrame; 
    Mat mOrig; 
    mFrame = imread("R2TsZ.png"); 
    mFrame.copyTo(mOrig); 
    Mat mOrigHull; 
    Mat mOut; 
    int fileCounter = 0; 
    while(true){ 
    clog<< "image read"<< endl; 
    cvtColor(mFrame, mOut, CV_BGR2GRAY); 
    clog<< "image grayscaled"<< endl; 
    Polygons contours; 
    Polygons aContours; 
    Polygons hulls; 
    OutputArray hierarchy = {}; 

    findContours(mOut, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); 
    clog<< contours.size()<< " contours found"<< endl; 
    sort(contours.begin(), contours.end(), [](auto p1, auto p2){ 
     return contourArea(p1) > contourArea(p2); 
    }); 
    clog<< "contours sorted"<< endl; 
    aContours.resize(contours.size()); 
    hulls.resize(contours.size()); 
    for(size_t i = 0; i < aContours.size() - 1; ++ i){ 
     approxPolyDP(contours[i], aContours[i], 20, true); 
     drawContours(mFrame, aContours, i, Scalar(255, 255, 255), 10); 
     convexHull(aContours[i], hulls[i], true); 
    } 
    mOrig.copyTo(mOrigHull); 
    for(size_t i = 0; i < 3; ++ i){ 
     drawContours(mOrigHull, hulls, i, Scalar(0, 0, 255), 10); 
    } 
    imshow("out", mOrigHull); 
    int key = waitKey() & 0xff; 
    if(key == 27){ 
     return EXIT_SUCCESS; 
    } 
    if(key == 'p'){ 
     string file = "test_" + to_string(++ fileCounter) + ".png"; 
     imwrite(file, mOrigHull); 
     clog<< file<< " saved."<< endl; 
    } 
    } 
} 

Xem thêm tại tutorial này từ opencv.

enter image description here

Các vấn đề liên quan