2016-05-24 5 views
10

Как сгладить края этого двоичного изображения кровеносных сосудов, полученных после порогового значения.Сглаживающие края двоичного изображения

enter image description here

Я попробовал метод несколько похож на this method, но не совсем получить результат я ожидал.

enter image description here

Вот код:

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) 

Что можно сделать, чтобы улучшить сглаживание этих суровых краях?

EDIT

Я хотел бы, чтобы сгладить края что-то вроде http://pscs5.tumblr.com/post/60284570543. Как это сделать в OpenCV?

+1

Смотрите, если [это] (http://stackoverflow.com/a/34535023/2571705) является то, что вы хотите. – dhanushka

+0

попробуйте использовать операцию numpy на циферблате, это mutch быстрее, чем операция пикселя за пикселем. – user5698387

+0

Возможно, вы могли бы более подробно описать, что вы ожидаете ... – tfv

ответ

11

Вот результат я получил с вашим изображением: enter image description here

Мой метод в основном базируется на нескольких cv::medianBlur наносят на масштабном вверх изображения.

Вот код:

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

Неровные края в связи с пороговым. Если вам комфортно выводить изображение, которое не является бинарным (то есть с 256 оттенками grAy), вы можете просто удалить его, и вы получите это изображение: enter image description here

+0

Это лучший результат. Я подтвердил ваш ответ, если в ближайшие дни я не получу лучших ответов, я приму этот ответ. Любые идеи о http://pscs5.tumblr.com/post/60284570543 –

+0

В этом сообщении применяется только реальная операция GaussianBlur. Затем он настраивает уровни, чтобы получить более резкие края. В вашем случае дефекты изображения слишком выражены, чтобы их можно было исправить простым размытием Гаусса.Вы можете попытаться применить размытие Gaussian к моему результату, но я полагаю, что это будет похоже на второе изображение, которое я разместил. – Sunreef

4

Затем вы можете разветвить области 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 ти масштабном Facor от 4 до вещи enter image description here

+0

Привет. Можете ли вы опубликовать несколько примеров кода и результатов, если это возможно? –

+0

Я скоро отредактирую – user5698387

+0

есть то, что я имею в виду! – user5698387

3

Что вы можете сделать, это увеличить разрешение изображения (например, двойной или тройной его с помощью resize). После этого эрозия и дилатация, как описано в другом ответе выше, приведут к более тонким результатам.

+1

Мы связаны с мозгом? я только что закончил с коэффициентом масштабирования 4, и это лучше, но с новым исходным изображением в наших руках мы можем сделать лучше :) – user5698387

2

Возможно, у вас, скорее всего, изображение кровеносных сосудов серого масштаба сначала, а затем пороговое значение. Он по-прежнему выглядит негладким, потому что исходное изображение в сером цвете имеет шум внутри. Теперь попросить о сглаживании краев приведет к более низкому разрешению. Например, разбавление и эрозия, предложенные в another answer, могут сливать соседние сосуды на стадии разбавления, которые затем не могут быть снова разделены на стадии эрозии.

Может быть предпочтительнее сначала удалить шум в изображении с серой шкалой (а также сделать сглаживание) и сделать пороговое значение в качестве последнего шага.

Поскольку вы не доставляли изображение с серой шкалой, я выполнил мягкое сглаживание (около одной ширины пикселя) здесь на двоичном изображении и снова выполнил пороговое значение.

enter image description here

Я сделал разглаживание (с гауссовым ядром фиксированного размера) и пороговый (с параметром) порогов. Я предлагаю вам сделать это в данных изображения в градациях серого и настроить два параметра, пока вам не понравится результат.

Matlab код в случае представляет интерес:

% 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

я сделал некоторые изменения в @dhanushka «s answer for another question и получить эти изображения.

Извините, это код на C++, но, возможно, вы преобразуете его в Python.

enter image description here

Вы можете изменить параметры ниже, чтобы получить разные результаты.

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

 Смежные вопросы

  • Нет связанных вопросов^_^