Сегментація зображень засобами openCV

Сегментація — це процес розділення цифрового зображення на декілька сегментів. Сегменти якісно просегментованого зображення повинні бути однорідними за текстурою, межі виділених сегментів повинні бути чіткими, сусідні сегменти повинні відрізнятися за певними критеріями. Загалом, усі методи сегментації можна поділити на такі категорії: методи, що базуються на кластеризації, методи з використанням гістограми, методи розростання областей, методи розрізу графа, водорозподілу, методи, що базуються на виділенні країв, багатомасштабна сегментація.
Виділення країв. Межі та краї областей сильно пов'язані, оскільки часто існує сильний перепад яскравості на кордонах областей. Тому методи виділення країв використовуються як основа для іншого методу сегментації. Приклад коду для виділення контурів з використанням детектора Кенні та результати при різних параметрах наведено нижче:

                            
/** * Детектор Кенні * @param image - Вхідне зображення * @param size - нижній поріг * @return Mat результат */ public static Mat cannyDetection(Mat image, int size){ Mat grayImage = new Mat(); Mat detectedEdges = new Mat(); // cконвертація у градації сірого Imgproc.cvtColor(image, grayImage, Imgproc.COLOR_BGR2GRAY); // видалення шумів Imgproc.blur(grayImage, detectedEdges, new Size(3, 3)); Imgproc.Canny(detectedEdges, detectedEdges, size, size/3, 3, false); return detectedEdges; }

K-means — це ітераційний метод, який використовується для того, щоб розділити зображення на K кластерів. Базовий алгоритм наведений нижче:
1. Вибрати K центрів кластерів, випадково або на основі деякої евристики
2. Помістити кожен піксель зображення в кластер, центр якого найближче до цього пікселя
3. Знову визначити центри кластерів, усереднюючи всі пікселі в кластері
4. Повторювати кроки 2 і 3 до збіжності (наприклад, коли пікселі будуть залишатися в тому ж кластері) Джерело

                            
/** * @param src - вхідне зображення * @return Mat результат */ public static Mat kmeans(Mat src){ Mat mHSV = new Mat(); Imgproc.cvtColor(src, mHSV, Imgproc.COLOR_RGBA2RGB,3); Imgproc.cvtColor(src, mHSV, Imgproc.COLOR_RGB2HSV,3); List hsv_planes = new ArrayList(3); Core.split(mHSV, hsv_planes); Mat channel = hsv_planes.get(0); channel = Mat.zeros(mHSV.rows(),mHSV.cols(),CvType.CV_8UC1); hsv_planes.set(2,channel); Core.merge(hsv_planes,mHSV); Mat clusteredHSV = new Mat(); mHSV.convertTo(mHSV, CvType.CV_32FC3); TermCriteria criteria = new TermCriteria(TermCriteria.EPS + TermCriteria.MAX_ITER,200,0.1); Core.kmeans(mHSV, 3, clusteredHSV, criteria, 30, Core.KMEANS_PP_CENTERS); return mHSV; }

Метод водоподілу - це, заснований на областях. метод математичної морфології. Вододіл — це хребет, який ділить області різних річкових систем Лінії вододілу — це кордони, що розділяють ділянки зображень. Перетворення водоподілу обчислює водозбірні басейни та лінії хребтів, при тому що водозбірні басейни — відповідні області зображення, а лінії хребтів — це межі цих областей. Недолік - можлива надмірна сегмментація
Програмний код наведено тут



Порогова сегментація. Один із основних і найпростіших способів - це побудова сегментації за допомогою порогу. Поріг - це ознака (властивість), що допомагає розділити шуканий сигнал на класи. Операція порогового поділу полягає в зіставленні значення яскравості кожного пікселя зображення з заданим значенням порога.
Приклад програмної реалізації наведено нижче: https://github.com/olehpitsun/CVforStudents/tree/master/src/task3/SegmentationMethods

                            
Imgproc.threshold(src1, frame, minValue, maxValue, Imgproc.THRESH_BINARY_INV + Imgproc.THRESH_OTSU);


Програмний код : https://github.com/olehpitsun/CVforStudents/tree/master/src/task2