Обнаружение черных точек из цветного фона

Мой короткий вопрос

Как определить черные точки на следующих изображениях? (Я вставляю только одно тестовое изображение, чтобы вопрос выглядел компактным. Еще изображения можно найти → здесь ←).

enter image description here

Мой длинный вопрос

Как показано выше, цвет фона примерно синий, а цвет точек - черный. Если выбрать один черный пиксель и измерить его цвет в RGB, значение может быть enter image description here (0, 44, 65) или enter image description here (14, 69, 89).... Поэтому мы не можем установить диапазон, чтобы сказать пиксель является частью черной точки или фона.

Я тестирую 10 изображений разных цветов, но надеюсь, что смогу найти метод обнаружения черных точек из более сложного фона, который может состоять из трех или более цветов, если человеческие глаза могут легко идентифицировать черные точки, Некоторые чрезвычайно маленькие или размытые точки можно опустить.

Предыдущая работа

В прошлом месяце я спросил аналогичный вопрос в stackoverflow, но не получил идеального решения, хотя некоторые отличные ответы. Узнайте больше о моей работе, если вы заинтересованы.

Вот методы, которые я пробовал:

  • Преобразование в оттенки серого или яркость изображения. Трудность заключается в том, что я не могу найти адаптивный порог для бинаризации. Очевидно, что превращение цветного изображения в оттенки серого или использование яркости (HSV) потеряет много полезной информации. Алгоритм Otsu, который вычисляет адаптивный порог, также не может работать.

  • Расчет гистограммы RGB. В моем последнем вопросе метод natan - оценить черный цвет по гистограмме. Это экономит время, но адаптивный порог также является проблемой.

  • Кластеризация. Я пробовал k-mean clustering и нашел его достаточно эффективным для фона, который имеет только один цвет. Недостаток (см. Мой собственный ответ) заключается в том, что мне нужно заранее установить количество центров кластеризации, но я не знаю, как это будет происходить. Что еще, это слишком [сильный] медленный! Мое приложение предназначено для захвата в реальном времени на iPhone, и теперь он может обрабатывать 7 ~ 8 кадров в секунду, используя k-средства (20 FPS хороши, я думаю).

Резюме

Я думаю, что не только похожие цвета, но и соседние пиксели должны быть "сгруппированы" или "объединены", чтобы извлечь черные точки. Пожалуйста, направляйте мне правильный способ решить мою проблему. Любые советы или алгоритмы будут оценены. Нет бесплатного обеда, но я надеюсь на лучший компромисс между ценой и точностью.

Ответы

Ответ 1

Мне удалось получить несколько хороших результатов первого прохода, перейдя в цветовое пространство HSV с помощью rgb2hsv, а затем используя Image Processing Toolbox функции imopen и imregionalmin в канале значений

rgb = imread('6abIc.jpg');
hsv = rgb2hsv(rgb);
openimg = imopen(hsv(:, :, 3), strel('disk', 11));
mask = imregionalmin(openimg);
imshow(rgb);
hold on;
[r, c] = find(mask);
plot(c, r, 'r.');

И полученные изображения (для изображения в вопросе и один, выбранный из вашей ссылки):

enter image description here

enter image description here

Вы можете увидеть несколько ложных срабатываний и пропущенных точек, а также несколько точек, помеченных несколькими точками, но несколько уточнений (например, изменение элемента структуры, используемого на шаге открытия) могут очистить их.

Ответ 2

Мне было интересно проверить мой старый 2d пиковый поисковый код на изображения без любого порога или любого цвета соображения, действительно сырые, как вы думаете?

im0=imread('Snap10.jpg');
im=(abs(255-im0));
d=rgb2gray(im);
filter=fspecial('gaussian',16,3.5);
p=FastPeakFind(d,0,filter);
imagesc(im0); hold on
plot(p(1:2:end),p(2:2:end),'r.')

enter image description here

Код, который я использую, - это простой двумерный локальный поиск максимумов, есть некоторые ложные срабатывания, но в целом это захватывает большинство точек без дублирования. Фильтр, который я использовал, был 2d gaussian ширины и std, аналогичный типичному blob (лучше всего было бы получить согласованный фильтр для вашей проблемы). Более сложная версия, которая обрабатывает цвета (rgb2hsv?), Может улучшить это далее...

Ответ 3

Вот необычно упрощенная версия, которая может быть расширена до полного RGB, а также не использует библиотеку обработки изображений. В основном вы можете выполнить двухмерную свертку с изображением фильтра (который является примером точки, которую вы ищете), и из точек, где свертка возвращает самые высокие значения, являются лучшими совпадениями для точек. Тогда вы можете, конечно, порог. Вот простой пример двоичного изображения именно этого.

%creating a dummy image with a bunch of small white crosses
im = zeros(100,100);
numPoints = 10;

% randomly chose the location to put those crosses
points = randperm(numel(im));
% keep only certain number of points
points = points(1:numPoints);
% get the row and columns (x,y)
[xVals,yVals] = ind2sub(size(im),points);

for ii = 1:numel(points)
   x = xVals(ii);
   y = yVals(ii);
   try
       % create the crosses, try statement is here to prevent index out of bounds
       % not necessarily the best practice but whatever, it is only for demonstration
       im(x,y) = 1;
       im(x+1,y) = 1;
       im(x-1,y) = 1;
       im(x,y+1) = 1;
       im(x,y-1) = 1;
   catch err
   end
end
% display the randomly generated image
imshow(im)

% create a simple cross filter
filter = [0,1,0;1,1,1;0,1,0];
figure; imshow(filter)

% perform convolution of the random image with the cross template
result = conv2(im,filter,'same');

% get the number of white pixels in filter
filSum = sum(filter(:));

% look for all points in the convolution results that matched identically to the filter
matches = find(result == filSum);

%validate all points found
sort(matches(:)) == sort(points(:))
% get x and y coordinate matches
[xMatch,yMatch] = ind2sub(size(im),matches);

Я бы очень хотел взглянуть на документацию conv2 на веб-сайте MATLAB.