GOOGLE ADS

Donnerstag, 14. April 2022

Wie bekomme ich das Bildpixel an realen Orten in opencv?

Ich möchte das RGB eines Pixels im Bild abrufen. Aber der Ort ist kein ganzzahliger Ort, sondern reale Werte (x,y). Ich möchte einen bilinear interpolierten Wert. Wie könnte ich es opencv tun?

Vielen Dank


Lösung des Problems

Es gibt keine einfache Funktion für den Zugriff auf Subpixel, aber ich kann Ihnen einige Optionen vorschlagen:

  • Verwenden Sie getRectSubPix und extrahieren Sie 1 Pixelbereich:

    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);
    }

  • Verwenden Sie eine flexiblere, aber weniger präzise Neuzuordnung mit einer Ein-Pixel-Karte:

    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);
    }

  • Implementieren Sie bilineare Interpolation selbst, da es keine Raketenwissenschaft ist:

    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);
    }
  • Keine Kommentare:

    Kommentar veröffentlichen

    Warum werden SCHED_FIFO-Threads derselben physischen CPU zugewiesen, obwohl CPUs im Leerlauf verfügbar sind?

    Lösung des Problems Wenn ich das richtig verstehe, versuchen Sie, SCHED_FIFO mit aktiviertem Hyperthreading ("HT") zu verwenden, ...