2016-03-22 6 views
1

Şu anda sahip olduğum bu sorunu çözmek için biraz yardıma ihtiyacım var. Ben sadece farklı şeyler, aynı zamanda Mavi, Yeşil ve Kırmızı temsil eden 3 görüntü var. Onları birleştirmem ve renkli bir görüntü almam gerekiyor. Ben opencv ve C++ kullanıyorum, ama şimdi bunu çözemediğim bu sorunu yaşıyorum. Kenar algılama üzerinde çalışma GEREKLİ:İHTİYAÇ: .İlk Sobel türevini bir kere x ve y yönünde bir kez hesaplayın ve bu iki (her kanal için) birleştirin

---- Güncelleme ---- ben bu sonucu bad example

olsun Ama böyle olmalı bazı yeni kodu

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

yazdı. correct one

---- TAM KOD -----

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_ bunları birleştirmek ki?Her gri görüntü için 'büyüklüğü' hesaplar ve daha sonra 3 büyüklüğü eklerim. (kırpma önlemek için float görüntüleri kullanın) – Miki

+0

addWeighted fonksiyonu ile çalışması gerekir.Ama gerçekten hiçbir ipucu ile değilim şimdi – twistedhat

+0

Gönderdim ve bazı örnekler ile cevap. Kodu yazmayı denemeden not aldığımı not edin, hatalar olabilir ... ama bunun için bildiğim – Miki

cevap

1

Sen eşikleme şunlara eşik min ile sobel_image. görüntüsünün minimum değeri olduğundan, min, 0 Ancak, neredeyse her zaman 0 olacaktır.

Degrade içermeyen bir pikselin sobel_L1_norm'da 0 değerine sahip olacağını unutmayın.

Bunun çözümü, eşik için anlamlı bir değer seçmektir. Değerleri [0, 255] aralığında normalleştirdiğinizden, o aralıkta bir değer seçebilirsiniz (0'dan büyük).

[0,1]'daki değerlerle normalize ederseniz, bu aralıkta bir değer seçin.


yerine maksimum bulma ve rescaling ait normalize(..., NORM_MINMAX) kullanabilirsiniz.


Ayrıca edgeThresholdthreshold çağrısının tip CV_32F bir matris olacak özen, bu nedenle de img_r_edge olacak. Görüntüyü imwrite ile düzeltmek için [0,1] aralığındaki CV_32F görüntülerini veya CV_8U görüntü aralıklarını [0,255] aralıklarla kullanın. Yani 'u [0,1] aralığında yeniden boyutlandırmaya veya CV_8U'a dönüştürmeye ihtiyacınız vardır.


Burada bir çok OpenCV türünü karıştırıyorsunuz. Türü tam olarak bilmek için Mat_<Tp>'u kullanmak genellikle daha kolaydır.

CV_32F görüntüleri ile her zaman [0,1] aralığında aralıklarla çalışabilirsiniz. önerilen değişikliklerle doğru çıktı, üretecek


Kodu:

#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

fikrini anlamalısın, ama bunu büyük bir yöntem kullanmadan yapmam gerek. Dün yazdığım bazı kodları yayınladım, ama eşiğim bana görüntüyü beyaz arka plan verdi, siyah arka plan ve beyaz çizgiler olurdu. – twistedhat

+0

Lütfen bir [mcve] gönderip deneyebilirim böylece – Miki

+0

Yukarıda bazı yeni kodlar yazdım, eğer main.cpp dosyasını ekleyebilirseniz kendiniz görebilirsiniz. – twistedhat

İlgili konular