Цель: я пытаюсь получить размер радужной оболочки (ширина / радиус), используя видео в качестве входных данных.
Я пробовал HoughCircles, но кажется, что это не точно, поскольку круг радужной оболочки, кажется, не так точен. У меня уже есть информация о центре зрачка глаза и его радиусе.
Мне было предложено найти край радужной оболочки, чтобы попытаться измерить величину градиента, начиная с центра зрачка, идущего наружу. Затем использовать гистограмму, используя накопление максимума градиента, чтобы найти ширину радужной оболочки. Я не совсем уверен, каким образом это реализовать, начиная с определенного момента.
Я использовал оператор Sobel на ROI глаза, чтобы попытаться получить градиент с выводом, показанным ниже.
Собел код изображения:
void irisFind(Mat gradMat, Point2i pupCenter, int pupRad){
imshow("original", gradMat);Mat gradX;
Mat gradY;
Mat absGradX;
Mat absGradY;
GaussianBlur(gradMat, gradMat, Size(3, 3), 0, 0, BORDER_DEFAULT);
equalizeHist(gradMat, gradMat);
//Generate Gradient along x
Sobel(gradMat, gradX, CV_16S, 1, 0, 3, 1, 0, BORDER_DEFAULT);
convertScaleAbs(gradX, absGradX);
//Generate Gradient along y
Sobel(gradMat, gradY, CV_16S, 0, 1, 3, 1, 0, BORDER_DEFAULT);
convertScaleAbs(gradY, absGradY);
addWeighted(absGradX, .5, absGradY, .5, 0, gradMat);
imshow("Sobel", gradMat);
}
Я не совсем уверен, как действовать дальше. Любые предложения или комментарии приветствуются. Также, пожалуйста, дайте мне знать, если я пропустил какую-либо информацию или я был расплывчатым в чем-то. Большое спасибо заранее!
РЕДАКТИРОВАТЬ: я должен был объяснить контекст моей заявки лучше, поэтому я прошу прощения за это. Я измеряю расширение зрачка глаза по кадрам с видео входа. Я уже знаю местоположение центральной точки зрачка и радиус зрачка. Я пытаюсь найти размер радужной оболочки, чтобы вариации расстояния от глаза до камеры можно было использовать для компенсации неверно истолкованных значений размера зрачка, поскольку, если глаз станет ближе к камере, зрачок, конечно, появится больше без расширения. Я мог бы также попробовать другие способы объяснить это, такие как уголки глаз, но я подумал, что, поскольку у меня уже есть несколько особенностей зрачка, я бы начал с радужной оболочки глаза.
Опять же, извините за то, что вы оставили эту деталь раньше. Спасибо!
Уточнение предложения, о котором вы говорите в своем вопросе:
«Мне было предложено найти край радужной оболочки, чтобы попытаться измерить величину градиента, начиная с центра зрачка, направленного наружу. Затем использовать гистограмму, используя накопление максимума градиента, чтобы найти ширину радужной оболочки. Я не совсем уверен каким образом реализовать это, начиная с определенной точки «.
Что конкретно вы можете сделать, так это начать со своего центра зрачка и выполнить алгоритм увеличения области, в котором ваше условие остановки вместо, скажем, слишком другого значения уровня серого является порогом для величины вашего градиента. Некоторый псевдокод:
initalize list of points with center of your pupil
initialize a mask image to zero
while list of point is not empty
point pt = pop()
set maskImage at pt to 255
for pt2 in pt neighbourhood
if (gradientMagnitude at pt2 < THRESHOLD and maskImage at pt2 == 0)
list of points.add (pt2)
Я думаю, что вы должны использовать тот факт, что внутри радужной оболочки есть черный круг.
Вот что я получил после простой сегментации черного цвета на вашем изображении:
И кажется, что настоящий ирис в 3 или 4 раза больше этого черного круга. Итак, вот результат:
Ищете исходный код? Это оно:
int main()
{
Mat src = imread("input.jpg", CV_LOAD_IMAGE_GRAYSCALE), tmp;
imshow("Source", src);
double minVal = 0;
minMaxLoc(src, &minVal, NULL, NULL, NULL);
threshold(src, tmp, minVal + 10, 255, THRESH_BINARY_INV);
//(Optional) remove noise (small areas of white pixels)
/*
Mat element = getStructuringElement(MORPH_ELLIPSE, Size(3, 3), Point(1, 1));
erode(tmp, tmp, element);
dilate(tmp, tmp, element);
*/
vector<Vec4i> hierarchy;
vector<vector<Point2i> > contours;
findContours(tmp, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
//find contour with max area
int maxArea = 0;
Rect maxContourRect;
for (int i=0; i<contours.size(); i++)
{
int area = contourArea(contours[i]);
Rect rect = boundingRect(contours[i]);
double squareKoef = ((double) rect.width)/rect.height;
//check if contour is like square (shape)
#define SQUARE_KOEF 1.5
if (area>maxArea && squareKoef < SQUARE_KOEF && squareKoef > 1.0/SQUARE_KOEF)
{
maxArea = area;
maxContourRect = rect;
}
}
if (maxArea == 0)
{
std::cout << "Iris not found!" << std::endl;
}
else
{
Rect drawRect = Rect(maxContourRect.x-maxContourRect.width, maxContourRect.y-maxContourRect.height, maxContourRect.width*3, maxContourRect.height*3);
rectangle(src, drawRect, Scalar(0), 1);
imshow("Dest", src);
waitKey();
}
}