2016-03-22 14 views
1

私は今この問題を理解するために何か助けが必要です。 私は、異なるものだけが同じである3つの画像を持っています、彼らは青、緑、赤を表しています。私はそれらを組み合わせて、色付きのイメージを取り戻す必要があります。 私はopencvとC++を使用していますが、今私はこの問題を把握できません。xで1回、y方向に1回、第1ソーベルの導関数を計算し、これらの2つを結合してください(チャンネルごとに)

が必要です。エッジ検出には、が必要です。

----更新---- は、私はこの結果bad example

を得る。しかし、それはこのようにする必要があり、いくつかの新しいコード

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

を書きました。 correct one

---- FULL CODE -----

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_あなたがそれらを結合するのでしょうか?私は各グレー画像の「大きさ」を計算して、3つの大きさを追加します。 (クリップを避けるために浮動小数点画像を使用する) – Miki

+0

これは関数addWeighted.Butで動作するはずです。実際には手がかりがありません – twistedhat

+0

私はいくつかの例を掲示して答えました。私は実際にそれを試みることなくコードを書き留めることに注意してください、間違いがあるかもしれません...しかし、あなたはその考えを理解する必要があります – Miki

答えて

1

あなたは、閾値minであなたのsobel_imageを閾値されています。

minは、画像の最小値であるため、(ほとんど)常に0になります。グラデーションのないピクセルの値は、に0となることに注意してください。

解決策は、しきい値に意味のある値を選択することです。値を正規化して[0, 255]の範囲にするので、その範囲の値を選択できます(0より大きい値)。

[0,1]の値で正規化する場合は、この間隔で値を選択します。


あなたは最大の発見と再スケーリングの代わりにnormalize(..., NORM_MINMAX)を使用することができます。


また、それはまたimg_r_edgeになりますのでedgeThresholdは、thresholdの呼び出し後タイプCV_32Fの行列になることに注意してください。画像をimwriteと正確に保存するには、範囲またはCV_8Uの画像をCV_32Fの範囲[0,255]の範囲で使用してください。したがっての範囲でimg_r_edgeを再スケーリングするか、CV_8Uに変換する必要があります。


ここでは多くのOpenCVタイプを混在させています。正確にタイプを知るには、通常Mat_<Tp>を使用する方が簡単です。

CV_32Fイメージでは、[0,1]の範囲でいつでも作業できます。


提案の修正で、正しい出力を生成しますコード:

#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

私はそれを知っていますが、私は振幅方法を使用せずにこれを行う必要があります。私は昨日書いたコードを投稿しますが、私の閾値は私にイメージの白い背景を与え、黒の背景と白の「線」になります。 – twistedhat

+0

私はそれを試すことができるように[mcve]を投稿してください – Miki

+0

私はあなたが自分で見ることができるように私はmain.cppファイルを添付することができます好きなら上のいくつかの新しいコードを書いた。 – twistedhat

関連する問題