2015-02-27 2 views
5

Я работаю над изображениями сетчатки сетчатки. Изображение состоит из круговой сетчатки на черном фоне. С OpenCV мне удалось получить контур, который окружает всю циркулярную сетчатку. Мне нужно вырезать круговую сетчатку с черного фона.Как обрезать внутреннюю область контура?

+2

Что вы имеете в виду под обрезкой? изображения всегда прямоугольны, поэтому вы можете создать маску и выполнить следующие операции (обработка/рендеринг) только на замаскированных пикселях. Или вы можете обрезать изображение так, чтобы оно было представлено ограничивающей рамкой сетчатки, которая может быть намного меньше исходного изображения, но все равно будет иметь некоторые черные части (так как сетчатка не прямоугольная).Или вы можете обрезать до максимальной прямоугольной области INSIDE сетчатки, у которой не осталось бы никаких черных фоновых пикселей, но также удалите части сетчатки. Какой вы хотите? – Micka

+2

Если это последний сценарий, попробуйте http://stackoverflow.com/questions/21410449/how-do-i-crop-to-largest-interior-bounding-box-in-opencv/21479072#21479072 – Micka

+0

@GauravPatil - Хотя этот ответ несколько лет, я постоянно получаю ответы на свой ответ ... что означает, что это, вероятно, правильно. Если это вам каким-то образом поможет, я был бы признателен, если бы вы согласились с ответом, чтобы люди знали, что вам больше не нужна помощь в этом отношении. Благодаря! – rayryeng

ответ

17

В вашем вопросе неясно, хотите ли вы обрезать информацию, определенную в контуре, или замаскировать информацию, не относящуюся к выбранному контуру. Я исследую, что делать в обеих ситуациях.


Маскировка информацию

Предполагая, что вы запускали cv2.findContours на изображении, вы получили структуру, которая содержит список всех контуров, имеющихся в изображении. Я также предполагаю, что вы знаете индекс контура, который использовался для окружающего объекта. Предполагая, что это хранится в idx, сначала используйте cv2.drawContours, чтобы нарисовать заполненную версию этого контура на пустое изображение, а затем используйте это изображение для индексации на изображении, чтобы извлечь объект. Эта логика маскирует любую нерелевантную информацию и сохраняет только то, что важно, - которое определено в выбранном контуре. Код, чтобы сделать это будет выглядеть примерно следующим, предполагая, что ваше изображение черно-белое изображение, сохраненное в img:

import numpy as np 
import cv2 
img = cv2.imread('...', 0) # Read in your image 
contours, _ = cv2.findContours(...) # Your call to find the contours 
idx = ... # The index of the contour that surrounds your object 
mask = np.zeros_like(img) # Create mask where white is what we want, black otherwise 
cv2.drawContours(mask, contours, idx, 255, -1) # Draw filled contour in mask 
out = np.zeros_like(img) # Extract out the object and place into output image 
out[mask == 255] = img[mask == 255] 

# Show the output image 
cv2.imshow('Output', out) 
cv2.waitKey(0) 
cv2.destroyAllWindows() 

Если вы действительно хотите обрезать ...

Если вы хотите урожая изображения, вам нужно определить минимальный ограничивающий ограничивающий прямоугольник области, определенной контуром. Вы можете найти верхний левый и нижний правый угол ограничительной рамки, а затем использовать индексирование, чтобы вырезать то, что вам нужно. Код будет таким же, как и раньше, но будет еще один шаг кадрирования:

import numpy as np 
import cv2 
img = cv2.imread('...', 0) # Read in your image 
contours, _ = cv2.findContours(...) # Your call to find the contours 
idx = ... # The index of the contour that surrounds your object 
mask = np.zeros_like(img) # Create mask where white is what we want, black otherwise 
cv2.drawContours(mask, contours, idx, 255, -1) # Draw filled contour in mask 
out = np.zeros_like(img) # Extract out the object and place into output image 
out[mask == 255] = img[mask == 255] 

# Now crop 
(x, y) = np.where(mask == 255) 
(topx, topy) = (np.min(x), np.min(y)) 
(bottomx, bottomy) = (np.max(x), np.max(y)) 
out = out[topx:bottomx+1, topy:bottomy+1] 

# Show the output image 
cv2.imshow('Output', out) 
cv2.waitKey(0) 
cv2.destroyAllWindows() 

код кадрирования работает таким образом, что, когда мы определяем маску, чтобы извлечь из области, определенный контур, мы дополнительно найти минимальные горизонтальные и вертикальные координаты, определяющие верхний левый угол контура. Мы также находим наибольшие горизонтальные и вертикальные координаты, определяющие нижний левый угол контура. Затем мы используем индексирование с этими координатами, чтобы обрезать то, что нам действительно нужно. Обратите внимание, что это выполняет обрезку на изображении в масках - это изображение, которое удаляет все, кроме информации, содержащейся в самом большом контуре.

Отмечают с OpenCV 3.x

Следует отметить, что приведенный выше код предполагает, что вы используете OpenCV 2.4.x. Обратите внимание, что в OpenCV 3.x было изменено определение cv2.drawContours. В частности, выход представляет собой вывод из трех элементов кортежа, где первое изображение является исходным изображением, тогда как остальные два параметра такие же, как в OpenCV 2.4.x. Поэтому просто измените оператор cv2.findContours в приведенном выше коде, чтобы игнорировать первый выход:

_, contours, _ = cv2.findContours(...) # Your call to find contours 
+0

@RedetGetachew - Нет, координаты не меняются местами. Выходной файл 'np.where' предоставляет расположение строк в' x' и столбцах в 'y', которые отличны от нуля. Поэтому индексирование в массив правильное. Пожалуйста, на самом деле проверьте свои изменения, прежде чем предлагать редактирование. – rayryeng