Цвет ключа функции обнаружения OpenCV C ++ из пикселя изображения [дубликат]

Попробуйте добавить боковую панель интерфейса к вашему методу подписки:

this.sidebarService.getSidebar().subscribe((sidebar: Sidebar) => {
    this.sidebar = sidebar.content;
});

interface Sidebar {
    _id?: string;
    content?: string;
}
14
задан Shan 9 November 2012 в 01:00
поделиться

4 ответа

Нет простой функции для доступа к подпикселю, но я могу предложить несколько вариантов:

  1. Используйте getRectSubPix и извлеките область 1 пиксель:
    cv::Vec3b getColorSubpix(const cv::Mat& img, cv::Point2f pt)
    {
        cv::Mat patch;
        cv::getRectSubPix(img, cv::Size(1,1), pt, patch);
        return patch.at<cv::Vec3b>(0,0);
    }
    
  2. Используйте более гибкий, но менее точный remap с однопиксельной картой:
    cv::Vec3b getColorSubpix(const cv::Mat& img, cv::Point2f pt)
    {
        cv::Mat patch;
        cv::remap(img, patch, cv::Mat(1, 1, CV_32FC2, &pt), cv::noArray(),
            cv::INTER_LINEAR, cv::BORDER_REFLECT_101);
        return patch.at<cv::Vec3b>(0,0);
    }
    
  3. Реализуйте билинейную интерполяцию самостоятельно, так как это не наука о ракетах:
    cv::Vec3b getColorSubpix(const cv::Mat& img, cv::Point2f pt)
    {
        assert(!img.empty());
        assert(img.channels() == 3);
    
        int x = (int)pt.x;
        int y = (int)pt.y;
    
        int x0 = cv::borderInterpolate(x,   img.cols, cv::BORDER_REFLECT_101);
        int x1 = cv::borderInterpolate(x+1, img.cols, cv::BORDER_REFLECT_101);
        int y0 = cv::borderInterpolate(y,   img.rows, cv::BORDER_REFLECT_101);
        int y1 = cv::borderInterpolate(y+1, img.rows, cv::BORDER_REFLECT_101);
    
        float a = pt.x - (float)x;
        float c = pt.y - (float)y;
    
        uchar b = (uchar)cvRound((img.at<cv::Vec3b>(y0, x0)[0] * (1.f - a) + img.at<cv::Vec3b>(y0, x1)[0] * a) * (1.f - c)
                               + (img.at<cv::Vec3b>(y1, x0)[0] * (1.f - a) + img.at<cv::Vec3b>(y1, x1)[0] * a) * c);
        uchar g = (uchar)cvRound((img.at<cv::Vec3b>(y0, x0)[1] * (1.f - a) + img.at<cv::Vec3b>(y0, x1)[1] * a) * (1.f - c)
                               + (img.at<cv::Vec3b>(y1, x0)[1] * (1.f - a) + img.at<cv::Vec3b>(y1, x1)[1] * a) * c);
        uchar r = (uchar)cvRound((img.at<cv::Vec3b>(y0, x0)[2] * (1.f - a) + img.at<cv::Vec3b>(y0, x1)[2] * a) * (1.f - c)
                               + (img.at<cv::Vec3b>(y1, x0)[2] * (1.f - a) + img.at<cv::Vec3b>(y1, x1)[2] * a) * c);
    
        return cv::Vec3b(b, g, r);
    }
    
33
ответ дан Andrey Kamaev 28 August 2018 в 15:22
поделиться

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

cv::Point2f current_pos; //assuming current_pos is where you are in the image

//bilinear interpolation
float dx = current_pos.x-(int)current_pos.x;
float dy = current_pos.y-(int)current_pos.y;

float weight_tl = (1.0 - dx) * (1.0 - dy);
float weight_tr = (dx)       * (1.0 - dy);
float weight_bl = (1.0 - dx) * (dy);
float weight_br = (dx)       * (dy);

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

4
ответ дан Hammer 28 August 2018 в 15:22
поделиться

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

Я думал, что мне хотелось бы, чтобы какая-то интуиция о том, какой из подходов является самым быстрым.

Я реализовал 3 метода из ответа Андрея Камаева, а также простого ближайшего соседа (в основном просто округляя координаты ).

Я провел эксперимент с матрицей A (100x100), которую я просто заполнил мусором. Затем я сделал матрицу B (400x400), которая заполнена значениями, интерполированными из a такими, что: B (i, j) = A (i / 4, j / 4).

Каждый прогон был выполнен 1000 и среднее время:

  • Ближайший сосед: 2.173 мс
  • getRectSubPix: 26.506 ms
  • remap: 114.265 ms
  • : 5.086 ms
  • руководство без borderInterpolate: 3.842 ms

Так что ближайший сосед для сверхскоростной скорости, если вы действительно не слишком заботитесь об актуальной интерполяции и просто нужно значение - особенно если ваши данные изменяются очень плавно. Для всего остального я бы пошел с ручной билинейной интерполяцией, поскольку он кажется последовательно быстрее других методов. (OpenCV 2.4.9 - Ubuntu 15.10 Repo - февраль 2016).

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

2
ответ дан kleinric 28 August 2018 в 15:22
поделиться

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

1
ответ дан Vlad 28 August 2018 в 15:22
поделиться