2016-03-22 1 views
1

j'ai besoin d'aide pour comprendre ce problème ce que j'ai en ce moment. J'ai 3 images qui sont les mêmes que les différentes choses, c'est qu'ils représentent bleu, vert et rouge. Je dois les combiner et récupérer une image colorée. J'utilise opencv et C++, mais maintenant j'ai ce problème que je n'arrive pas à comprendre.dérivé Calculer le 1er Sobel une fois en x et une fois dans la direction y et combiner ces deux (pour chaque canal)

Nécessaires: travaillant sur la détection de bord.

---- ---- Mise à jour j'ai écrit un nouveau code de

Sobel(img_r, x, CV_16S, 1, 0); 
    Sobel(img_r, y, CV_16S, 0, 1); 
    //Compute the L1 norm 
    sobel_L1_norm = abs(x)+abs(y); 
    //Find Sobel max value 
    minMaxLoc(sobel_L1_norm, &min, &max); 
    sobel_L1_norm.convertTo(sobel_image, CV_32F, 255.0/(max - min), -min * 255.0/(max - min)); 
    threshold(sobel_image, edgeThreshold, min, 255, THRESH_BINARY); 
    edgeThreshold.copyTo(img_r_edge); 

Je reçois ce résultat bad example

Mais il devrait être comme ça. correct one

---- CODE COMPLET -----

Mat img_r = imread(input_path + "/01.png", CV_LOAD_IMAGE_GRAYSCALE); 
Mat img_g = imread(input_path + "/02.png", CV_LOAD_IMAGE_GRAYSCALE); 
Mat img_b = imread(input_path + "/03.png", CV_LOAD_IMAGE_GRAYSCALE); 
// Edge Images 
Mat img_r_edge = Mat::zeros(img_r.size(), CV_8UC1); 
Mat img_g_edge = Mat::zeros(img_g.size(), CV_8UC1); 
Mat img_b_edge = Mat::zeros(img_b.size(), CV_8UC1); 

std::cout << "Step 1 - calculating edge images... "; 
    // TODO: 1) Calculate the 1st Sobel derivative once in x and once in y direction and combine these two 
    //   (for every channel). 
    Mat x; 
    Mat y; 
    Mat abs_x; 
    Mat abs_y; 
    Mat sobel_L1_norm; 
    Mat sobel_image; 
    Mat edgeThreshold; 
    double min, max; //Finding min and max Sobel valuye; 


    //--------------------------------------------------- 

    Sobel(img_r, x, CV_16S, 1, 0); 
    Sobel(img_r, y, CV_16S, 0, 1); 
    //Compute the L1 norm 
    sobel_L1_norm = abs(x)+abs(y); 
    //Find Sobel max value 
    minMaxLoc(sobel_L1_norm, &min, &max); 
    sobel_L1_norm.convertTo(sobel_image, CV_32F, 255.0/(max - min), -min * 255.0/(max - min)); 
    threshold(sobel_image, edgeThreshold, min, 255, THRESH_BINARY); 
    edgeThreshold.copyTo(img_r_edge); 

    //---------------------------------------------------- 


    //  2) Normalize every gradient image and convert the results to CV_8UC1. 
    //  3) Threshold the retrieved (normalized) gradient images using the parameter "edgeThreshold". 
    //  4) Save the results in the cv::Mats below. 

    imwrite(out_r_edge_filename, sobel); 
    imwrite(out_g_edge_filename, img_g_edge); 
    imwrite(out_b_edge_filename, img_b_edge); 
+1

_How_-vous les combiner?Je calcule la «magnitude» pour chaque image grise, puis j'ajoute la magnitude 3. (Utilisez les images flottantes pour éviter l'écrêtage) – Miki

+0

Il devrait fonctionner avec la fonction addWeighted.But je suis vraiment sans aucune idée en ce moment – twistedhat

+0

J'ai posté et répondre avec quelques exemples. Notez que j'écris le code sans vraiment l'essayer, il peut y avoir des erreurs ... mais vous devez comprendre l'idée – Miki

Répondre

1

Vous seuillage votre sobel_image avec un seuil min.

Cependant min sera (presque) toujours 0, puisque c'est la valeur minimale de l'image sobel_L1_norm. Notez qu'un pixel sans gradient aura une valeur de 0 dans sobel_L1_norm.

La solution est de choisir une valeur significative pour le seuil. Puisque vous normaliser les valeurs pour qu'elles soient dans la plage [0, 255], vous pouvez choisir une valeur dans cette plage (supérieure à 0).

Si vous normalisez avec des valeurs en [0,1], choisissez une valeur dans cet intervalle.


Vous pouvez utiliser normalize(..., NORM_MINMAX) au lieu de trouver le maximum et redimensionnant.


Aussi que edgeThreshold sera une matrice de type CV_32F après l'appel à threshold, il sera également img_r_edge. Pour enregistrer l'image correcly avec imwrite, dépérir utiliser CV_32F images dans la gamme [0,1] ou CV_8U images dans la gamme [0,255]. Vous devez donc redimensionner img_r_edge dans la plage [0,1] ou le convertir en CV_8U.


Vous mélangez beaucoup de types OpenCV ici. Il est généralement plus facile d'utiliser Mat_<Tp> pour connaître exactement le type.

Vous pouvez toujours travailler avec CV_32F images, avec une plage de [0,1].


code

qui produira une sortie correcte, avec des modifications proposées:

#include <opencv2/opencv.hpp> 
#include <vector> 
using namespace cv; 
using namespace std; 


int main() 
{ 
    Mat3b img = imread(path_to_color_image"); 

    vector<Mat1b> planes; 
    split(img, planes); 

    Mat1b img_r = planes[2].clone(); 
    Mat1b img_g = planes[1].clone(); 
    Mat1b img_b = planes[0].clone(); 

    // Edge Images 
    Mat1b img_r_edge; 
    Mat1b img_g_edge; 
    Mat1b img_b_edge; 

    // TODO: 1) Calculate the 1st Sobel derivative once in x and once in y direction and combine these two 
    //   (for every channel). 
    Mat1f dx, dy; 
    Mat1f sobel_L1_norm; 
    Mat1f sobel_image; 
    Mat1f edgeThreshold; 
    double min, max; //Finding min and max Sobel valuye; 


    //--------------------------------------------------- 

    Sobel(img_r, dx, CV_32F, 1, 0); 
    Sobel(img_r, dy, CV_32F, 0, 1); 

    //Compute the L1 norm 
    sobel_L1_norm = abs(dx) + abs(dy); // Type 

    // Normalize 
    normalize(sobel_L1_norm, sobel_image, 0, 1, NORM_MINMAX); 

    // Use a value different from 'min', which will (almost always) be 0. 
    double thresh = 0.5; 
    threshold(sobel_image, edgeThreshold, thresh, 255, THRESH_BINARY); 

    edgeThreshold.convertTo(img_r_edge, CV_8U); 
    imwrite("img_r_edge.png", img_r_edge); 


    return 0; 
} 
+0

Je sais pour cela, mais je dois le faire de cette façon sans utiliser la méthode de magnitude. Je poste du code que j'ai écrit hier, mais ma treshold me donne l'image de fond blanc, ce serait un fond noir et des 'lignes' blanches. – twistedhat

+0

S'il vous plaît poster un [mcve] afin que je puisse l'essayer – Miki

+0

j'ai écrit du nouveau code ci-dessus, si vous aimez je peux joint le fichier main.cpp afin que vous puissiez voir par vous-même. – twistedhat