Сравнение и нанесение областей одного цвета на набор данных из нескольких сотен изображений - PullRequest
1 голос
/ 02 июня 2019

Студент химии обратился ко мне за помощью в построении сегментации изображения: Стационарная камера делает снимок экспериментальной установки каждую секунду в течение нескольких минут, так что получается около 300 изображений.

Соответствующими частями в установке являются два смежных слоя пены разного цвета, наблюдаемые сбоку, в основном двухцветный сэндвич, сжимающийся с обеих сторон, за исключением того, что одна из пен испаряется немного быстрее.


Я бы хотел сегментировать каждое из изображений таким образом, чтобы я мог построить «ширину» обеих областей пены со временем.

Вот такая "диаграмма" :) Я хочу пойти отсюда -> Здесь

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


У меня немного опыта работы с Python и Matlab, но я никогда не использовал OpenCV или набор инструментов для обработки изображений в Matlab, или вообще никогда не имел дела с компьютерным зрением в целом. Не могли бы вы, ребята, дать пример того, какие пакеты / функции использовать или какие шаги следует предпринять, и я это сделаю?

Я не уверен, как решить эти вопросы:

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

- какую библиотеку использовать для сегментирования областей изображения в зависимости от их цвета (возможно, для некоторых k-средних махинаций) и выборочного хранения пространственных параметров результирующих сегментов?

- как повторить это для нескольких файлов.

Заранее благодарим вас!

Ответы [ 2 ]

0 голосов
/ 02 июня 2019

Предположим, что ваша интенсивность изменится после преобразования в шкалу серого (если нет, просто конвертируйте в другое цветовое пространство, такое как HSV или LAB, а затем просто используйте один из компонентов)

img = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

Первый , пороговые значения в градациях серого в несколько полос

ret,thresh1 = cv.threshold(img,128,255,cv.THRESH_BINARY)
ret,thresh2 = cv.threshold(img,27,255,cv.THRESH_BINARY_INV)
ret,thresh3 = cv.threshold(img,77,255,cv.THRESH_TRUNC)
ret,thresh4 = cv.threshold(img,97,255,cv.THRESH_TOZERO)
ret,thresh5 = cv.threshold(img,227,255,cv.THRESH_TOZERO_INV)

Значение должно быть проверено вашими фактическими данными. Здесь я просто приведу пример

Очистите сегментированное изображение с помощью медианного фильтра с радиусом больше 9. Я ожидаю некоторого шума. Вы также можете использовать ROI здесь, чтобы помочь удалить часть шума. Но лично мне лень, я просто написал программу для обработки всех случаев и угла

threshholed_images_aftersmoothing = cv2.medianBlur(threshholed_images,9)

Каждая полоса будет соответствовать одному цвету (слою). Теперь у вас должно быть N сегментированного изображения из одного источника. где N - количество слоев, которые вы хотите отслеживать

Секунда Используйте ограничивающий прямоугольник функции opencv, чтобы найти местоположение и ширину / высоту каждого слоя АКА каждый threshholed_images_aftersmoothing . Например. Граничная привязка на каждом подсегментированном изображении.

C++: Rect boundingRect(InputArray points)
Python: cv2.boundingRect(points) → retval¶

Last , прямоугольник имеет свойство x, y, height и width. Вы можете использовать простой порядок сортировки для сортировки сверху вниз на основе прямоугольного атрибута x. Запустите хотя бы все vieo, чтобы получить x (слой ID), график высоты и времени.

Rect API

Public Attributes
_Tp     **height**   // this is what you are looking for

_Tp     width  

_Tp     **x**   // this tells you the position of the band

_Tp     y

Построив соответствующие высоты (| AB | или | CD |) с течением времени, вы можете получить график, который вам нужен.

Более правильный способ - использовать фильтр Калмана для отслеживания графика положения и высоты, так как я ожидаю, что возникнет какой-то пузырь, который будет влиять на высоту слоев.

Если честно, я не ожидал, что студент-химик будет в этом хорош. Хаха, удачи

Что-то не так, вы можете найти меня здесь или напишите мне, если я не смотрю stackoverflow

0 голосов
/ 02 июня 2019

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

Если, например, вы используете ширину 3 пикселя для roi, результатом 300 изображений будет изображение шириной 900 пикселей, где слеваэто начало эксперимента, а право это конец.Следующее изображение может помочь вам понять:

enter image description here

Хотя я еще не полностью протестировал его, этот код должен работать.Обратите внимание, что в папке, на которую вы ссылаетесь, должны быть только изображения.

import cv2
import numpy as np 
import os

# path to folder that holds the images
path = '.'
# dimensions of roi
x = 0
y = 0
w = 3
h = 100

# store references to all images
all_images = os.listdir(path)
# sort images
all_images.sort()
# create empty result array
result = np.empty([h,0,3],dtype=np.uint8)

for image in all_images:
        # load image
        img = cv2.imread(path+'/'+image)
        # get the region of interest
        roi = img[y:y+h,x:x+w]
        # add the roi to previous results 
        result = np.hstack((result,roi))

# optinal: save result as image
# cv2.imwrite('result.png',result)
# display result - can also plot with matplotlib
cv2.imshow('Result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

Обновление после редактирования вопроса:
Если пены имеют разные цвета, вы можете легко разделить их по цвету, преобразовав изображение, которое выhsv и использование inrange (пример) .Это создает маску (= 2D-массив со значениями от 0 до 255, по одному на каждый пиксель), которую можно использовать для вычисления средней высоты и извлечения параметров и области изображения.

Вы можете найти скрипт, который поможет вам найти цвета HSV для разделения на этом GitHub

...