Isolate object to better detect it

asked 2020-07-04 04:45:41 -0500

albeh95 gravatar image

Hello everyone, it's me again: i'm trying to detect dome trees in a pictures and I tryed different ways. At the end I chose a BOW+SVM approach, by creating a dictionary and then applying it to the .train(...) of my SVM. I found out that this isn't enough for what I have to do, since classification gives me wrong result. So I tried a treshold on my test images by applying a clustering for colors, but of course, grass is detected too, so it's not very helpful. My training images (for dictionary and SVM training) are all .png images (so tress without background) and that's why I'm trying to segment my test images to isolate trees. I have tried some basic OpenCV segmentation tecniques (found here) but they don't seem to work. Here's my code:

Mat dictionary;
FileStorage fs("myDictionary.yml", FileStorage::READ);
fs["vocabulary"] >> dictionary;

Ptr<SIFT> detector = SIFT::create(); //detector to detect SIFT features 
Ptr<DescriptorExtractor> extractor = SIFT::create();
Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create(DescriptorMatcher::FLANNBASED);

BOWImgDescriptorExtractor bowDE(extractor, matcher);

cout << "extracting histograms in the form of BOW for each Training image " << endl;
Mat labels(0, 1, CV_32S);
cout << labels.size() << endl;
int dictSize = 200;

Mat trainingData;
int k = 0;
vector<KeyPoint> keypoint;
Mat bowDescriptor;
Mat img;

vector<String> fn;
glob("C:/Users/albma/Desktop/train/*.png", fn, true);

for (size_t i = 0; i < fn.size(); i++) { //trees: label = 1

    printf("Training Image = %s\n", fn[i]);
    img = imread(fn[i], 0);
    detector->detect(img, keypoint); //detect keypoints
    bowDE.compute(img, keypoint, bowDescriptor); //compute descriptors
    labels.push_back((int)1); //push labels in a matrix.. 1

cout << trainingData.size() << endl;
cout << labels.size() << endl;

//SVM Part

Ptr<ml::SVM> svm = ml::SVM::create();
svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6));*/
printf("Training SVM\n");
Ptr<TrainData> td = TrainData::create(trainingData, ROW_SAMPLE, labels); //start training SVM

Mat testData(0, dictSize, CV_32FC1);
k = 0;
vector<KeyPoint> keypoint2;
Mat bowDescriptor2;

printf("Training Done... loading Test images \n");

vector<String> fnb;
glob("C:/Users/albma/Desktop/Università/Computer Vision/final_project_test/Benchmark_step_1/*.jpg", fnb, true);

Mat results(0, 1, CV_32FC1);

Mat segm;
Mat test = imread("Figure 1.jpg");
inRange(test, Scalar(0, 23, 0), Scalar(11, 255, 34), segm);
imshow("test", segm);

for (int i = 0; i < fnb.size(); i++) {
    printf("Test Image = %s\n", fnb[i]);
    img = imread(fnb[i]);

    Mat data;
    img.convertTo(data, CV_32F);
    data = data.reshape(1,;

    Mat labels, centers;
    kmeans(data, 8, labels, TermCriteria(TermCriteria::MAX_ITER, 10, 1.0), 3,
        KMEANS_PP_CENTERS, centers);

    centers = centers.reshape(3, centers.rows);
    data = data.reshape(3, data.rows);

    Vec3f *p = data.ptr<Vec3f>();
    for (size_t i = 0; i < data.rows; i++) {
        int center_id =<int>(i);
        p[i] =<Vec3f>(center_id);

    img = data.reshape(3, img.rows);
    img.convertTo(img, CV_8U);

    inRange(img, Scalar(0, 23, 0), Scalar(11, 255, 34), segm ...
edit retag flag offensive close merge delete


Another strategy I'm trying is to delete the grass part in the image treshold (maybe by selecting only "dense" white part) and then get back to the original image by applyng bitwise_and(...), but don't know how to implement it. Also, am i supposed to make transparent the black part of the treshold?

albeh95 gravatar imagealbeh95 ( 2020-07-04 04:59:05 -0500 )edit

I managed to get only the trees in the treshold, however I only get non-trees labels on every test pic... don't get why

albeh95 gravatar imagealbeh95 ( 2020-07-04 09:14:28 -0500 )edit