2016-07-24 14 views
0

Wie kann ich das rote Objekt in dem Bild unten mit opencv in Android finden und es mit meinem Muster füllen wie im zweiten Bild?Wie finde ich ein Objekt in opencv und ersetze das durch ein neues Bild in Android?

Ich muss eine App erstellen, um die Wand mit einem Maskierungsmuster automatisch zu füllen und wenn der Benutzer auf ein Bildmuster klickt, dann füllt das Bild mit dem ausgewählten Muster.

Bitte erwähnen Sie eine Bibliothek, die dies tut.

Vielen Dank für Ihre Hilfe.

enter image description here enter image description here

Antwort

0

C++ Version, nicht geeignet für den direkten Einsatz in Android

ich eine Lösung für Ihr Problem entwickelt; ist nicht perfekt, aber Sie können es versuchen. Bitte beachten Sie, dass die roten Bereiche wirklich rot sein müssen, also RGB (255,0,0). In dem Bild, das Sie zur Verfügung gestellt hatten, waren die roten Regionen nicht perfekt rot.

#include <iostream> 
#include <vector> 
#include <opencv2/opencv.hpp> 

cv::Mat fillWall(cv::Mat homeImage, cv::Mat screenshot); 

int main() 
{ 
    cv::Mat originalImage = cv::imread("original2.png"); 
    cv::Mat maskImage = cv::imread("maks.jpg"); 
    cv::Mat finalImage = fillWall(originalImage, maskImage); 
    cv::imshow("result", finalImage); 
    cv::waitKey(5000); 
    return 0; 
} 

cv::Mat fillWall(cv::Mat originalImage, cv::Mat pattern) 
{ 
    cv::Mat output; 
    cv::Mat rectHome; 

    // Preproc 
    cv::cvtColor(originalImage, originalImage, CV_RGBA2BGR); 
    // Select only red regions in the originalImage. 
    cv::inRange(originalImage, cv::Scalar(254, 0, 0), cv::Scalar(255, 0, 0), rectHome); 
    cv::Mat originalMask; 
    rectHome.copyTo(originalMask); 
    originalImage.copyTo(output); 

    // Contours 
    std::vector<std::vector<cv::Point>> allContours; 
    std::vector<std::vector<cv::Point>> contours; 
    allContours.reserve(10); 
    cv::findContours(rectHome, allContours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE); 
    for (auto &c : allContours) { 
    if (c.size() > 50) { 
     contours.push_back(c); 
    } 
    } 

    // Find the rotated rectangles for each contour 
    // This approx the contours to rectangles. 
    std::vector<cv::RotatedRect> minRect; 
    for(size_t i = 0; i < contours.size(); i++) { 
    minRect.push_back(cv::minAreaRect(cv::Mat(contours[i]))); 
    } 

    for (int ci = 0; ci < minRect.size(); ci++) { 
    cv::Point2f pointsRes[4], pointsIn[4]; 
    pointsIn[0] = cv::Point2f(10, 10) ; 
    pointsIn[1] = cv::Point2f(pattern.cols - 10, 10); 
    pointsIn[2] = cv::Point2f(pattern.cols - 10, pattern.rows - 10); 
    pointsIn[3] = cv::Point2f(10, pattern.rows - 10); 

    cv::Point2f rect[4]; 
    minRect[ci].points(rect); 
    pointsRes[3] = rect[2]; 
    pointsRes[2] = rect[3]; 
    pointsRes[1] = rect[0]; 
    pointsRes[0] = rect[1]; 

    // Do a perspective transform in order to display 
    // the pattern image with the correct orientation 
    cv::Mat prsxTrnsf = cv::getPerspectiveTransform(pointsIn, pointsRes); 
    cv::Mat outScreen; 
    cv::warpPerspective(pattern, outScreen, prsxTrnsf, cv:: Size(originalImage.cols , originalImage.rows)); 
    cv::cvtColor(outScreen, outScreen, CV_BGRA2RGB); 

    for (int row = 0; row < originalImage.rows; row++) { 
     for (int col = 0; col < originalImage.cols; col++) { 
     double inside = cv::pointPolygonTest(contours[ci], cv::Point2f(col,row), false); 
     if (originalMask.at<uchar>(row, col) == 255 && inside >= 0) { 
      output.at<cv::Vec3b>(row, col) = outScreen.at<cv::Vec3b>(row, col); 
     } 
     } 
    } 
    } 
    cv::cvtColor(output, output, CV_BGR2RGBA); 
    return output; 
} 

Output image

anzumerken, dass das Musterbild gedreht zufällig ist; Wenn Sie mir sagen, wie Sie das Muster wollen, kann ich es einstellen. Ich denke, dass dies ein guter Anfang ist.

+0

Was ist die Programmiersprache? ndk? oder ...? bitte posten Sie hier den Link wie Sie wie Sie auf Android arbeiten. Vielen vielen Dank. –

+0

Sorry, ich habe total vergessen, dass Android Java bedeutet. Dies ist C++ - Code, den Sie nicht direkt in einer Android-App verwenden können. Ich denke, Sie haben hier zwei Möglichkeiten: Versuchen Sie, den Code mit dem OpenCV für Java zu übersetzen, oder verwenden Sie direkt den obigen C++ - Code unter folgendem Link: http://docs.opencv.org/2.4.2/doc/tutorials/introduction/android_binary_package /android_binary_package_using_with_NDK.html –

+0

In jedem Fall können Sie den Algorithmus in der Funktion * fillWall * vorgeschlagen und übersetzen für Android, sollte nicht schwierig sein. –

Verwandte Themen