Это не из-за неправильных параметров. Ограничивается сама часть сегментации изображения.
Пороговое значение на основе серого не может работать, если контраст между блобом и фоном очень низок. Однако пороговое значение около 160 вполне допустимо в этом примере, но не является точным.
Я предлагаю пойти для определения цвета на основе порога, так как есть приличный цветовой разрыв.
Ниже приведена реализация пороговых значений на основе цвета на C++. Блоки отфильтровываются с использованием того же SimpleBlobDetector.
Я преобразовал изображение с RGB to ‘Lab’ для лучшей сегментации.
Поскольку изображение предоставлено слишком велико, потребовалось больше времени для обработки. Поэтому я обрезал ключевую часть изображения и настраивал параметры blob для того же самого. Поэтому я также предоставляю обрезанное изображение (755 x 494px).
Цвет на основе порогового значения и блоб фильтрации:
#include "opencv2\imgproc\imgproc.hpp";
#include "opencv2\highgui\highgui.hpp";
#include "opencv2\features2d\features2d.hpp";
using namespace cv;
using namespace std;
void main()
{
char image_path[] = "E:/Coding/media/images/leaf_small.jpg";
Mat img_color, img_lab, img_thresh, img_open, img_close, img_keypoints;
img_color = imread(image_path, IMREAD_ANYCOLOR);
//Convert image to CIE Lab colorspace for better colour based segmentation
cvtColor(img_color, img_lab, CV_BGR2Lab);
//create window before creating trackbar
namedWindow("win_thresh", WINDOW_NORMAL);
namedWindow("win_blob", WINDOW_NORMAL);
//Using trackbar calculate the range of L,a,b values to seperate blobs
int low_L = 150, low_A = 0, low_B = 155,
high_L = 255, high_A = 255, high_B = 255;
//*Use trackbars to caliberate colour thresholding
createTrackbar("low_L", "win_thresh", &low_L, 255);
createTrackbar("low_A", "win_thresh", &low_A, 255);
createTrackbar("low_B", "win_thresh", &low_B, 255);
createTrackbar("high_L", "win_thresh", &high_L, 255);
createTrackbar("high_A", "win_thresh", &high_A, 255);
createTrackbar("high_B", "win_thresh", &high_B, 255);
int minArea = 35, maxArea = 172, minCircularity = 58, minConvexity = 87, minInertiaRatio = 21;
//Use trackbar and set Blob detector parameters
createTrackbar("minArea", "win_blob", &minArea, 200);
createTrackbar("maxArea", "win_blob", &maxArea, 200);
createTrackbar("minCircular", "win_blob", &minCircularity, 99);
createTrackbar("minConvex", "win_blob", &minConvexity, 99);
createTrackbar("minInertia", "win_blob", &minInertiaRatio, 99);
SimpleBlobDetector::Params params;
vector<KeyPoint> keypoints;
while (waitKey(1) != 27) //press 'esc' to quit
{
//inRange thresholds basedon the Scalar boundaries provided
inRange(img_lab, Scalar(low_L, low_A, low_B), Scalar(high_L, high_A, high_B), img_thresh);
//Morphological filling
Mat strucElement = getStructuringElement(CV_SHAPE_ELLIPSE, Size(5, 5), Point(2, 2));
morphologyEx(img_thresh, img_close, MORPH_CLOSE, strucElement);
imshow("win_thresh", img_close);
//**SimpleBlobDetector works only in inverted binary images
//i.e.blobs should be in black and background in white.
bitwise_not(img_close, img_close); // inverts matrix
//Code crashes if minArea or any miin value is set to zero
//since trackbar starts from 0, it is adjusted here by adding 1
params.filterByArea = true;
params.minArea = minArea + 1;
params.maxArea = maxArea + 1;
params.filterByCircularity = true;
params.filterByConvexity = true;
params.filterByInertia = true;
params.minCircularity = (minCircularity + 1)/100.0;
params.minConvexity = (minConvexity + 1)/100.0;
params.minInertiaRatio = (minInertiaRatio + 1)/100.0;
SimpleBlobDetector detector(params);
detector.detect(img_close, keypoints);
drawKeypoints(img_color, keypoints, img_keypoints, Scalar(0, 0, 255), DrawMatchesFlags::DEFAULT);
stringstream displayText;
displayText = stringstream();
displayText << "Blob_count: " << keypoints.size();
putText(img_keypoints, displayText.str(), Point(0, 50), CV_FONT_HERSHEY_PLAIN, 2, Scalar(0, 0, 255), 2);
imshow("win_blob", img_keypoints);
}
return;
}
Выход Скриншот
Настройте параметры blob в соответствии с фактическим HD-изображением.
Поскольку жилы листа имеют почти одинаковый цвет и интенсивность тли, этот метод также может полностью потерпеть неудачу, когда тля находится близко или точно на вершине вены.
Это может быть специальным исправлением, но недостаточно надежным. Должен быть простой и надежный способ достижения результата, используя некоторые фильтры, преобразование или обнаружение краев. Пожалуйста, поделитесь любым другим оптимальным решением, если оно доступно.
EDIT: Opting Grayscale порогового, как предыдущий подход не удался
Цвета порогового подхода потерпел неудачу для this_image
Цвета основы порогового имеет очень узкую полосу пропускания, если изображение находится в пределах полосы пропускания, точность будет быть действительно хорошими, с другой стороны, изменения цвета полностью разрушают точность. Поскольку вы будете обрабатывать 100 изображений, цветовое ограничение может оказаться непригодным.
Я пробовал нормальное градиентное пороговое значение с некоторой морфологической эрозией и наполнением и получал приличную точность. Также пороговое значение шкалы серого имеет лучшую устойчивость к цветовым сдвигам.
Кроме того, у нас есть опция auto thrsholding с использованием OTSU Thresholding, которая выбирает пороговое значение на основе изображения.
Фрагмент кода:
threshold(img_gray, img_thresh, 0, 255, THRESH_OTSU);
Mat strucElement = getStructuringElement(CV_SHAPE_ELLIPSE, Size(3, 3), Point(1, 1));
morphologyEx(img_thresh, img_open, MORPH_OPEN, strucElement);
Остальной код остается неизменным.
Значения параметров:
minArea = 75, maxArea = 1000, minCircularity = 50, minConvexity = 20, minInertiaRatio = 15
Белые муравьи трудно отличить от тли, как мы не используем информацию о цвете. Поэтому необходимо тщательно настроить min_area
, чтобы исключить их.
Обработанные изображения можно найти здесь img_1, img_2.
Измените методы морфологии и параметры blob для получения оптимального среднего значения.
Просьба предоставить промежуточные изображения, например, ваше двоичное изображение. – Piglet