2016-05-24 14 views
10

Jak wygładzić krawędzie tego binarnego obrazu naczyń krwionośnych uzyskanych po progowaniu.Wygładzanie krawędzi obrazu binarnego

enter image description here

Próbowałem metodę nieco podobny do this method ale nie dość uzyskać wynik spodziewałem.

enter image description here

Oto kod:

import cv2 
import numpy as np 

INPUT = cv2.imread('so-br-in.png',0) 
MASK = np.array(INPUT/255.0, dtype='float32') 

MASK = cv2.GaussianBlur(MASK, (5,5), 11) 
BG = np.ones([INPUT.shape[0], INPUT.shape[1], 1], dtype='uint8')*255 

OUT_F = np.ones([INPUT.shape[0], INPUT.shape[1], 1],dtype='uint8') 

for r in range(INPUT.shape[0]): 
    for c in range(INPUT.shape[1]): 
     OUT_F[r][c] = int(BG[r][c]*(MASK[r][c]) + INPUT[r][c]*(1-MASK[r][c])) 

cv2.imwrite('brain-out.png', OUT_F) 

Co można zrobić, aby poprawić wygładzenie tych trudnych krawędzi?

EDIT

Chciałbym wygładzają krawędzie coś podobnego http://pscs5.tumblr.com/post/60284570543. Jak to zrobić w OpenCV?

+1

Sprawdź, czy [to] (http://stackoverflow.com/a/34535023/2571705) to, co chcesz. – dhanushka

+0

spróbuj użyć operacji numpy na macie, jest ona szybsza niż operacja piksel po pikselu – user5698387

+0

Może mógłbyś opisać bardziej szczegółowo to, czego się spodziewasz ... – tfv

Odpowiedz

11

Oto wynik uzyskałam z obrazka: enter image description here

Moja metoda opiera się głównie na kilku cv::medianBlur stosowanej na skalowane-up obraz.

Oto kod:

cv::Mat vesselImage = cv::imread(filename); //the original image 
cv::threshold(vesselImage, vesselImage, 125, 255, THRESH_BINARY); 
cv::Mat blurredImage; //output of the algorithm 
cv::pyrUp(vesselImage, blurredImage); 

for (int i = 0; i < 15; i++) 
    cv::medianBlur(blurredImage, blurredImage, 7); 

cv::pyrDown(blurredImage, blurredImage); 
cv::threshold(blurredImage, blurredImage, 200, 255, THRESH_BINARY); 

nierówne krawędzie są spowodowane Progowanie. Jeśli nie masz nic przeciwko obrazowi wyjściowemu, który nie jest binarny (tj. Z 256 odcieniami koloru), możesz go po prostu usunąć i otrzymasz następujący obraz: enter image description here

+0

To lepszy wynik. Poprawiłem twoją odpowiedź, jeśli nie otrzymam lepszych odpowiedzi w ciągu najbliższych kilku dni, przyjmuję tę odpowiedź. Wszelkie pomysły na temat http://pscs5.tumblr.com/post/60284570543 –

+0

W tym poście, jedyną operacją, która została zastosowana, jest GaussianBlur. Następnie dostosowuje poziomy, aby uzyskać ostrzejsze krawędzie. W twoim przypadku defekty na obrazie są zbyt wyraźne, aby można je było skorygować za pomocą zwykłego rozmycia Gaussa.Możesz spróbować zastosować rozmycie Gaussa do obrazu wynikowego, ale przypuszczam, że wyglądałoby jak drugi obraz, który zamieściłem. – Sunreef

4

Można rozszerzać, a następnie erodować obszary http://docs.opencv.org/2.4/doc/tutorials/imgproc/erosion_dilatation/erosion_dilatation.html.

import cv2 
import numpy as np 
blur=((3,3),1) 
erode_=(5,5) 
dilate_=(3, 3) 
cv2.imwrite('imgBool_erode_dilated_blured.png',cv2.dilate(cv2.erode(cv2.GaussianBlur(cv2.imread('so-br-in.png',0)/255, blur[0], blur[1]), np.ones(erode_)), np.ones(dilate_))*255) 

From To

EDIT whith facor skali od 4 przed rzeczy enter image description here

+0

. Czy możesz podać przykładowy kod i wyniki, jeśli to możliwe? –

+0

będę edytować wkrótce – user5698387

+0

jest co mam na myśli! – user5698387

3

Co można zrobić, to zwiększyć rozdzielczość obrazu (na przykład podwójne lub potrójne go za pomocą resize). Następnie erozja i rozszerzenie, jak opisano w drugiej odpowiedzi powyżej, doprowadzi do lepszych wyników.

+1

Czy jesteśmy podłączony do mózgu? Właśnie skończyłem to ze współczynnikiem skali 4 i jest lepiej, ale odrobinę nowego obrazu źródłowego w naszej ręce możemy zrobić lepiej :) – user5698387

2

Najprawdopodobniej masz obraz naczyń krwionośnych w skali szarości najpierw, a potem próg. Nadal wygląda niezbyt gładko, ponieważ oryginalny obraz w skali szarości miał wewnątrz szum. Pytanie o wygładzenie krawędzi spowoduje zmniejszenie rozdzielczości. Na przykład rozcieńczenie i erozja zaproponowane w another answer mogą fuzować sąsiednie naczynia w etapie rozcieńczania, który następnie nie może być ponownie rozdzielony w etapie erozji.

Zalecane może być najpierw usunięcie szumów na obrazie w skali szarości (również tam wygładzanie) i wykonanie progu jako ostatniego kroku.

Ponieważ nie dostarczyłeś obrazu w skali szarości, wykonałem tutaj łagodne wygładzanie (około jednego piksela) na obrazie binarnym i ponownie wykonałem operację progowania.

enter image description here

Zrobiłem wygładzanie (z jądrem Gaussa o stałej wielkości) i obcinanie (z parametrem progowania). Proponuję zrobić to na danych obrazu w skali szarości i dostosować te dwa parametry, dopóki nie polubisz wyniku.

kod Matlab w przypadku jest to odsetek:

% read 
img = imread('YyNQV.png'); 
img = double(img(:, :, 1) ~= 255); % png is RGB -> binary 

% smooth 
kernel = fspecial('gaussian', 10, 1.5); 
kernel = kernel/sum(kernel(:)); % normalize to 1 
img_smooth = conv2(img, kernel, 'same'); 

% binarize again 
threshold = 0.4; % experiment with values between 0 and 1 
img_smooth_threshold = img_smooth > threshold; 

% save (exchange black and white) 
imwrite(~img_smooth_threshold, 'YyNQV_smooth.png'); 
1

zrobiłem pewne modyfikacje na @dhanushka „s answer for another question i dostać te obrazy.

Przepraszamy, ale jest to kod w C++, ale możliwe, że przekonwertujesz go na język Python.

enter image description here

można zmienić poniżej parametry, aby uzyskać różne rezultaty.

// contour smoothing parameters for gaussian filter 
int filterRadius = 10; // you can try to change this value 
int filterSize = 2 * filterRadius + 1; 
double sigma = 20; // you can try to change this value 

enter image description here

#include <opencv2/highgui.hpp> 
#include <opencv2/imgproc.hpp> 
#include <iostream> 

using namespace cv; 
using namespace std; 

int main(int argc, const char** argv) 
{ 
    Mat im = imread(argv[1], 0); 

    Mat cont = ~im; 
    Mat original = Mat::zeros(im.rows, im.cols, CV_8UC3); 
    Mat smoothed = Mat(im.rows, im.cols, CV_8UC3, Scalar(255,255,255)); 

    // contour smoothing parameters for gaussian filter 
    int filterRadius = 5; 
    int filterSize = 2 * filterRadius + 1; 
    double sigma = 10; 

    vector<vector<Point> > contours; 
    vector<Vec4i> hierarchy; 
    // find contours and store all contour points 
    findContours(cont, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE, Point(0, 0)); 
    for(size_t j = 0; j < contours.size(); j++) 
    { 
     // extract x and y coordinates of points. we'll consider these as 1-D signals 
     // add circular padding to 1-D signals 
     size_t len = contours[j].size() + 2 * filterRadius; 
     size_t idx = (contours[j].size() - filterRadius); 
     vector<float> x, y; 
     for (size_t i = 0; i < len; i++) 
     { 
      x.push_back(contours[j][(idx + i) % contours[j].size()].x); 
      y.push_back(contours[j][(idx + i) % contours[j].size()].y); 
     } 
     // filter 1-D signals 
     vector<float> xFilt, yFilt; 
     GaussianBlur(x, xFilt, Size(filterSize, filterSize), sigma, sigma); 
     GaussianBlur(y, yFilt, Size(filterSize, filterSize), sigma, sigma); 
     // build smoothed contour 
     vector<vector<Point> > smoothContours; 
     vector<Point> smooth; 
     for (size_t i = filterRadius; i < contours[j].size() + filterRadius; i++) 
     { 
      smooth.push_back(Point(xFilt[i], yFilt[i])); 
     } 
     smoothContours.push_back(smooth); 

     Scalar color; 

     if(hierarchy[j][3] < 0) 
     { 
      color = Scalar(0,0,0); 
     } 
     else 
     { 
      color = Scalar(255,255,255); 
     } 
     drawContours(smoothed, smoothContours, 0, color, -1); 
    } 
    imshow("result", smoothed); 
    waitKey(0); 
} 
Powiązane problemy