Alenorze
@Alenorze
Не люблю Индию

Как соеденить два контура в OpenCV?

Всем привет, вообщем есть необычная задача, у меня есть сетка на tf которая берет фото с прической
5cfa954464dbd644646785.jpeg
И выдает островки(то что посчитала за волосы) на прозрачном фоне. Я беру самый большой контур(предположительно парик) и делаю вокруг него кроп. Но есть проблема, иногда фото обрезано сверху, или к примеру у девушки очень крутой пробор, парик из за этого делится на две части.
5cfa956088cf6976355118.png5cfa9a2391a49630535597.png

Вот функция
std::vector< int > gpuFindSides( InputArray image_mask )
{
    cuda::GpuMat image_mask_crop(image_mask);
    cuda::GpuMat mask_crop;
    cuda::GpuMat mask_crop_tr;
    cuda::GpuMat mask_crop_tr_8;
    Mat cropped_mask;
    
    cuda::threshold(image_mask_crop, mask_crop_tr, 0.1, 1.0, THRESH_BINARY);
    mask_crop_tr.convertTo(mask_crop_tr_8, CV_8UC1);
    mask_crop_tr_8.download(cropped_mask);

    std::vector<std::vector<Point> > contours;
    
    findContours(cropped_mask, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
    double maxArea = 0;
    int maxAreaContourId = -1;
    int w;
    int h;
    for (int j = 0; j < contours.size(); j++) {
        double newArea = contourArea(contours.at(j));
        if (newArea > maxArea) {
            maxArea = newArea;
            maxAreaContourId = j;
        }
    }
    Rect rect = boundingRect(contours[maxAreaContourId]);
    w = rect.width;
    h = rect.height;
    if (h * 1.2 <= w) {
        h = (int)(h * 2);
    }
    else if (h <= w){
        h = (int)(h * 1.5);
    }
    else if (h * 0.8 <= w){
        h = (int)(h * 1.3);
    }

    std::vector< int > arr;

    arr.push_back(rect.x);
    arr.push_back(rect.y);
    arr.push_back(w);
    arr.push_back(h);
         
    return arr;
}

Я не особо разбираюсь в плюсах, поэтому хотелось бы узнать как сделать хотя бы один из вариантов.
1. Соеденить все контуры и сделать один общий, вокруг которого сделать boundingRect.
2. Соеденить два самых больших контура но при условии что разница по площади не больше 20-30%
3. Увеличить площадь threshold тогда две части парика могут зацепить друг друга

Задача непростая, на решение не рассчитываю, но очень буду рад подсказкам
  • Вопрос задан
  • 610 просмотров
Решения вопроса 1
Alenorze
@Alenorze Автор вопроса
Не люблю Индию
Решением было поменять значение threshold с 0.1 на 0.01
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@grinat
У opencv есть биндинги под все известные и неизвестные языки, не понимаю что мешает взять биндинг под питон или любой другой <язык_нейм> и играться с ним. Если это парик, который подсовывается вместо прозрачных пикселей. то области не нужны, по идее достаточно получить x,y левого нижнего первого прозрачного пикселя и начиная с этой позиции вхерачить парик, дальше сверху наложить фото, у которого будут вырезаны все прозрачные пиксели.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы