Сегментация изображения по цвету фона – OpenCV Android

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

Например, такая карта: Пример визитной карточки

Должны быть разделены на два изображения, так как есть 2 цвета фона. Есть ли какие-либо предложения о том, как справиться с этим? Я попытался сделать какой-то контурный анализ, который не оказался слишком успешным.

Другие примеры карт: Введите описание изображения здесь

Эта карта должна давать 3 сегментации, так как есть три части, хотя это всего 2 цвета (хотя 2 цвета будут в порядке).

Введите описание изображения здесь

Вышеприведенная карта должна давать только одну сегментацию, так как это только один цвет фона.

Я пока не пытаюсь думать о градиентных фонах.

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

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

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

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

Изменить. Два новых изображения также показывают один и тот же шаблон. Цвет фона занимает большую часть изображения, нет шума и нет цветовых градиентов. Таким образом, простой подход может выглядеть следующим образом:

Если у вас есть примеры, которые не работают с этим подходом, просто опубликуйте их.

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

#include <opencv2/opencv.hpp> using namespace cv; using namespace std; Mat src; Mat src_gray; int canny_thresh = 100; int max_canny_thresh = 255; int size_per_mill = 120; int max_size_per_mill = 1000; RNG rng(12345); bool cmp_contour_area_less(const vector<Point>& lhs, const vector<Point>& rhs) { return contourArea(lhs) < contourArea(rhs); } void Segment() { Mat canny_output; vector<vector<Point> > contours; vector<Vec4i> hierarchy; Canny(src_gray, canny_output, canny_thresh, canny_thresh*2, 3); // Draw rectangle around canny image to also get regions touching the edges. rectangle(canny_output, Point(1, 1), Point(src.cols-2, src.rows-2), Scalar(255)); namedWindow("Canny", CV_WINDOW_AUTOSIZE); imshow("Canny", canny_output); // Find the contours. findContours(canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0)); // Remove largest Contour, because it represents always the whole image. sort(contours.begin(), contours.end(), cmp_contour_area_less); contours.resize(contours.size()-1); reverse(contours.begin(), contours.end()); // Maximum contour size. int image_pixels(src.cols * src.rows); cout << "image_pixels: " << image_pixels << "\n"; // Filter the contours, leaving just large enough ones. vector<vector<Point> > background_contours; for(size_t i(0); i < contours.size(); ++i) { double area(contourArea(contours[i])); double min_size((size_per_mill / 1000.0) * image_pixels); if (area >= min_size) { cout << "Background contour " << i << ") area: " << area << "\n"; background_contours.push_back(contours[i]); } } // Draw large contours. Mat drawing = Mat::zeros(canny_output.size(), CV_8UC3); for(size_t i(0); i < background_contours.size(); ++i) { Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255)); drawContours(drawing, background_contours, i, color, 1, 8, hierarchy, 0, Point()); } namedWindow("Contours", CV_WINDOW_AUTOSIZE); imshow("Contours", drawing); } void size_callback(int, void*) { Segment(); } void thresh_callback(int, void*) { Segment(); } int main(int argc, char* argv[]) { if (argc != 2) { cout << "Please provide an image file.\n"; return -1; } src = imread(argv[1]); cvtColor(src, src_gray, CV_BGR2GRAY); blur(src_gray, src_gray, Size(3,3)); namedWindow("Source", CV_WINDOW_AUTOSIZE); imshow("Source", src); if (!src.data) { cout << "Unable to load " << argv[1] << ".\n"; return -2; } createTrackbar("Canny thresh:", "Source", &canny_thresh, max_canny_thresh, thresh_callback); createTrackbar("Size thresh:", "Source", &size_per_mill, max_size_per_mill, thresh_callback); Segment(); waitKey(0); } 
Intereting Posts
Приложение не появляется на рынке Android / google play Android SnackBar падает при касании с помощью библиотеки поддержки дизайна 23.0.0 Обновление первого элемента gridview после того, как getView раздувает его дважды GetView вызывается только при прокрутке на уровне 8 андроида. Почему onCallStateChanged () на Android вызывается более одного раза за один раз? RawQuery Vs. database.query Поиск местоположений в определенном городе в Google Местах Apis Модернизация Более медленное время отклика в реальных устройствах Android по сравнению с эмулятором и сетью VerifyError с использованием Mockito 1.9.5 и DexMaker-Mockito-1.0 Как я могу исключить внешний .jar из obfuscation от Proguard (проект Android)? Зачем начинать исключать ресурсы моего собственного приложения, когда это было не нужно раньше? Tuple, от Python до Java ExpandableListView и флажки Как расширить класс SQLiteDatabase? Существует ли постоянное несъемное глобальное хранилище для приложений на каждом устройстве Android?