9

Ho cercato di fondere due immagini. L'approccio attuale che sto prendendo è che ottengo le coordinate della regione di sovrapposizione delle due immagini, e solo per le regioni sovrapposte, mi mischio con un alfa di 0,5, con codice di massa, prima di aggiungerlo. In pratica, sto semplicemente prendendo metà del valore di ogni pixel dalle regioni sovrapposte di entrambe le immagini e aggiungendole. Questo non mi dà una miscela perfetta perché il valore alfa è hardcoded a 0.5. Ecco il risultato della fusione di 3 immagini:Come ottenere il giusto valore alfa per unire perfettamente due immagini?

Come si può vedere, la transizione da un'immagine all'altra è ancora visibile. Come ottengo il perfetto valore alfa che eliminerebbe questa transizione visibile? O non c'è niente di simile, e sto prendendo un approccio sbagliato?

Ecco come Attualmente sto facendo la fusione:

for i in range(3): 
      base_img_warp[overlap_coords[0], overlap_coords[1], i] = base_img_warp[overlap_coords[0], overlap_coords[1],i]*0.5 
      next_img_warp[overlap_coords[0], overlap_coords[1], i] = next_img_warp[overlap_coords[0], overlap_coords[1],i]*0.5 
final_img = cv2.add(base_img_warp, next_img_warp) 

Se qualcuno volesse dare un colpo, qui ci sono due immagini deformate, e la maschera della loro regione di sovrapposizione: http://imgur.com/a/9pOsQ

+0

La fonte immagini sembrano essere pre-moltiplicato con sfondo. Potresti mostrare la formula che stai utilizzando finora? – K3N

+0

@ K3N, ho modificato e aggiunto del codice. Fammi sapere se questo aiuta. – Metal

+2

Potresti fornire le 3 immagini distinte deformate, così come le coordinate sovrapposte? Ciò consentirà alle persone di verificare approcci diversi. – Miki

risposta

8

Ecco il modo in cui lo farei in generale:

int main(int argc, char* argv[]) 
{ 
    cv::Mat input1 = cv::imread("C:/StackOverflow/Input/pano1.jpg"); 
    cv::Mat input2 = cv::imread("C:/StackOverflow/Input/pano2.jpg"); 

    // compute the vignetting masks. This is much easier before warping, but I will try... 
    // it can be precomputed, if the size and position of your ROI in the image doesnt change and can be precomputed and aligned, if you can determine the ROI for every image 
    // the compression artifacts make it a little bit worse here, I try to extract all the non-black regions in the images. 
    cv::Mat mask1; 
    cv::inRange(input1, cv::Vec3b(10, 10, 10), cv::Vec3b(255, 255, 255), mask1); 
    cv::Mat mask2; 
    cv::inRange(input2, cv::Vec3b(10, 10, 10), cv::Vec3b(255, 255, 255), mask2); 


    // now compute the distance from the ROI border: 
    cv::Mat dt1; 
    cv::distanceTransform(mask1, dt1, CV_DIST_L1, 3); 
    cv::Mat dt2; 
    cv::distanceTransform(mask2, dt2, CV_DIST_L1, 3); 

    // now you can use the distance values for blending directly. If the distance value is smaller this means that the value is worse (your vignetting becomes worse at the image border) 
    cv::Mat mosaic = cv::Mat(input1.size(), input1.type(), cv::Scalar(0, 0, 0)); 
    for (int j = 0; j < mosaic.rows; ++j) 
    for (int i = 0; i < mosaic.cols; ++i) 
    { 
     float a = dt1.at<float>(j, i); 
     float b = dt2.at<float>(j, i); 

     float alpha = a/(a + b); // distances are not between 0 and 1 but this value is. The "better" a is, compared to b, the higher is alpha. 
     // actual blending: alpha*A + beta*B 
     mosaic.at<cv::Vec3b>(j, i) = alpha*input1.at<cv::Vec3b>(j, i) + (1 - alpha)* input2.at<cv::Vec3b>(j, i); 
    } 

    cv::imshow("mosaic", mosaic); 

    cv::waitKey(0); 
    return 0; 
} 

Fondamentalmente è calcolare la distanza dal confine ROI al centro degli oggetti e calcolare l'alpe ha da entrambi i valori della maschera di fusione. Pertanto, se un'immagine ha una distanza elevata dal bordo e un'altra a bassa distanza dal bordo, preferisci il pixel più vicino al centro dell'immagine. Sarebbe meglio normalizzare quei valori per i casi in cui le immagini deformate non hanno dimensioni simili. Ma ancora meglio e più efficiente è precomputare le maschere di miscelazione e deformarle. La cosa migliore sarebbe conoscere la vignettatura del sistema ottico e scegliere una maschera di fusione identica (in genere valori inferiori del bordo).

Dal codice precedente si otterrà questi risultati: maschere ROI:

enter image description here

enter image description here

maschere di fusione (proprio come l'impressione, devono essere matrici pescante, invece):

enter image description here

enter image description here

immagine mosaico:

enter image description here

+0

Ehi, come hai ottenuto le maschere. 'cv2.distanceTransform (img_1_mask, cv2.DIST_L1, 3)' restituisce solo la maschera originale in python. – Metal

+0

prima di visualizzarlo devi ridimensionarli, perché i valori float> = 1 vengono visualizzati in bianco. Prova 'imshow (windowname, dt1/255)' o sth. come quello (non so sintassi numpy/python, scusa) – Micka

+0

È 'cv2.imshow (windowname, img/255)', grazie! Inoltre, chiedendo se c'è un modo più rapido per manipolare tutti i pixel, piuttosto che iterare su tutti loro. Qualche idea? – Metal

4

Ci sono 2 problemi evidenti con le immagini:

condizioni di luce
  1. zona di confine ha distorto

    Ciò è probabilmente causato dall'ottica utilizzata per acquisire immagini. Quindi, per rimediare, dovresti usare solo parte delle immagini (tagliare alcuni pixel dal bordo).

    Così, quando tagliare 20 pixel dal bordo e la miscelazione di illuminazione comune ho ottenuto questo:

    border cut off

    Come si può vedere la linea di giunzione confine brutto è lontano ora solo i problemi di illuminazione persiste (vedi proiettile # 2).

  2. immagini sono prese a diverse condizioni di illuminazione

    Qui sottosuolo disperdendo effetti colpisce nel rendere le immagini "non compatibile". Dovresti normalizzarli con un'illuminazione uniforme o post-processare il risultato miscelato riga per riga e quando l'urto coerente rilevato moltiplica il resto della linea in modo che l'urto sia diminuito.

    bump

    Così il resto della linea deve essere moltiplicato per costante i0/i1. Di questo tipo se i dossi possono verificarsi solo sui bordi tra i valori di sovrapposizione in modo da poterli cercare o usare direttamente quelle posizioni ... Per riconoscere un bump valido dovrebbe avere vicini vicini nelle linee precedenti e successive lungo l'intera altezza dell'immagine.

    È possibile farlo anche in direzione Y dell'asse nello stesso modo ...