2013-02-26 15 views
5

Zasadniczo chcę zaimplementować funkcję wymiany koloru dla mojej aplikacji malowania. Poniżej są oryginalne i oczekiwany wynikwymiana koloru w obrazie dla aplikacji iPhone

oryginalny: original

Po zmianie koloru ściany wybranej przez użytkownika wraz z pewnym progiem do wymiany

desired output próbowałem dwa podejścia, ale nie mógł dostał działa zgodnie z oczekiwaniami

Podejście 1:
Queue-based Flood Fill algorytm zastępowania kolorów: , ale otrzymałem poniżej wydajność z niesamowicie powolnym i cień ściany nie został zachowany.

flood fill output

Podejście 2: Więc próbowałem patrzeć na inną opcję i znaleźć poniżej słupka z tak How to change a particular color in an image?

ale nie mogłem zrozumieć logikę i nie wiesz o moim implementacji kodu z krok 3.

Proszę znaleźć poniżej kod dla każdego kroku mądry z moim zrozumieniem.

1) Konwertuj obraz z RGB na HSV, używając cvCvtColor (chcemy tylko zmienić kolor na ).

IplImage *mainImage=[self CreateIplImageFromUIImage:[UIImage imageNamed:@"original.jpg"]]; 
IplImage *hsvImage = cvCreateImage(cvGetSize(mainImage), IPL_DEPTH_8U, 3); 
IplImage *threshImage = cvCreateImage(cvGetSize(mainImage), IPL_DEPTH_8U, 3); 
cvCvtColor(mainImage,hsvImage,CV_RGB2HSV); 

2) izolowania kolor z cvThreshold określając pewną tolerancję (chcesz gamę kolorów, a nie jedno mieszkanie koloru).

cvThreshold(hsvImage, threshImage, 0, 100, CV_THRESH_BINARY); 

3) Zniszcz obszary koloru poniżej minimalnej wielkości za pomocą blob wykrywania biblioteki jak cvBlobsLib. Spowoduje to pozbycie się kropek o podobnym kolorze w scenie. Czy muszę podać oryginalny obraz lub zdjęcie z okresu świątecznego?

CBlobResult blobs = CBlobResult(threshImage, NULL, 0); 
blobs.Filter(blobs, B_EXCLUDE, CBlobGetArea(), B_LESS, 10); 

4) Maska koloru z cvInRangeS i użyć wynikającą maskę zastosować nowy odcień.

Not sure about this function, jak to pomaga w zastępowaniu kolorów i nie jest w stanie zrozumieć argumentów, które należy podać.

5) cMZmień nowy obraz z nowym odcieniem z obrazem złożonym z nasycenia i jasności kanałów zapisanych w kroku pierwszym.

Rozumiem, że cvMerge połączy się z trzema kanałami H S i V, ale jak mogę użyć wyjścia powyżej trzech kroków.

więc w zasadzie skazani realizacji OpenCV,

jeśli to możliwe to proszę kierować do mnie implementacja OpenCV lub jakimkolwiek innym roztworze Tryout'y.

+1

nie będzie wystarczająca do zmiany tylko odcienia w punkcie 4 i używać oryginalnego nasycenie krok 5. Spójrz na ścianę w twoim przykładzie. Jest szary. Nasycenie szarości jest zerowe (lub bardzo bliskie zeru), co oznacza, że ​​odcień nie ma żadnego efektu. Aby obrócić tę ścianę na niebiesko, musisz ustawić nasycenie na coś bliższego jednemu (* i * musisz ustawić odcień). –

+0

Rob myślisz, że mój drugi i trzeci krok są poprawne? –

+0

@JigarParekh Mam ten sam problem, ale muszę to zrobić w czasie rzeczywistym (czyli w obrazie z kamery), więc możesz udzielić wskazówek, jak to zrobić – Prabhakar

Odpowiedz

3

Wreszcie jestem w stanie osiągnąć pożądane wyniki za pomocą poniżej kodu javacv i ten sam przeniesiony do opencv też.

to rozwiązanie ma 2 problemy

  1. nie mają wykrywanie krawędzi, myślę, że za pomocą konturów mogę to osiągnąć
  2. zastąpić kolor ma płaski odcień i usiadł, które powinny wyznaczać na podstawie źródłowego pikseli odcienia różnica siedząca, ale nie wiem, jak to osiągnąć. może być zamiast cvSet pomocą cvAddS

    IplImage image = cvLoadImage("sample.png"); 
    CvSize cvSize = cvGetSize(image); 
    
    
    IplImage hsvImage = cvCreateImage(cvSize, image.depth(),image.nChannels()); 
    
    IplImage hChannel = cvCreateImage(cvSize, image.depth(), 1); 
         IplImage sChannel = cvCreateImage(cvSize, image.depth(), 1); 
         IplImage vChannel = cvCreateImage(cvSize, image.depth(), 1); 
    cvSplit(hsvImage, hChannel, sChannel, vChannel, null); 
    
    
    IplImage cvInRange = cvCreateImage(cvSize, image.depth(), 1); 
    CvScalar source=new CvScalar(72/2,0.07*255,66,0); //source color to replace 
    CvScalar from=getScaler(source,false); 
    CvScalar to=getScaler(source, true); 
    
    cvInRangeS(hsvImage, from , to, cvInRange); 
    
    IplImage dest = cvCreateImage(cvSize, image.depth(), image.nChannels()); 
    
    IplImage temp = cvCreateImage(cvSize, IPL_DEPTH_8U, 2); 
    cvMerge(hChannel, sChannel, null, null, temp); 
    
    cvSet(temp, new CvScalar(45,255,0,0), cvInRange);// destination hue and sat 
    cvSplit(temp, hChannel, sChannel, null, null); 
    cvMerge(hChannel, sChannel, vChannel, null, dest); 
    cvCvtColor(dest, dest, CV_HSV2BGR); 
    cvSaveImage("output.png", dest); 
    

metody do obliczania progu

CvScalar getScaler(CvScalar seed,boolean plus){ 
    if(plus){ 
     return CV_RGB(seed.red()+(seed.red()*thresold),seed.green()+(seed.green()*thresold),seed.blue()+(seed.blue()*thresold)); 
    }else{ 
     return CV_RGB(seed.red()-(seed.red()*thresold),seed.green()-(seed.green()*thresold),seed.blue()-(seed.blue()*thresold)); 
    } 
     } 
+0

dobra odpowiedź ... +1 – jagdish

+1

Czy możesz podzielić się z nami materiałem lub samouczkiem, do którego się odwołujesz? ta cecha ? Pracuję też nad podobną funkcjonalnością. Nie mogę znaleźć niczego odpowiedniego :( – Shailesh

+0

Byłoby wspaniale, gdybyś mógł podzielić się – woohoou

Powiązane problemy