Наилучшие параметры для обнаружения зрачка с помощью Hough? Java OpenCV
-------------- прочитайте изменить ниже --------------- Я пытаюсь обнаружить края зрачков и радужной оболочки в различных изображениях. Я изменяю параметры и тому подобное, но мне удается только когда-либо получить правильный контур ирисовой диафрагмы / зрачка, или получить ненужные контуры на заднем плане, или вообще ничего. Это некоторые конкретные параметры, которые я должен попытаться получить и получить правильные схемы. Или есть способ, которым я могу обрезать изображение только для глаз, чтобы система могла сфокусироваться на этой части?
Это мой ОБНОВЛЕННЫЙ метод:
private void findPupilIris() throws IOException {
//converts and saves image in grayscale
Mat newimg = Imgcodecs.imread("/Users/.../pic.jpg");
Mat des = new Mat(newimg.rows(), newimg.cols(), newimg.type());
Mat norm = new Mat();
Imgproc.cvtColor(newimg, des, Imgproc.COLOR_BGR2HSV);
List<Mat> hsv = new ArrayList<Mat>();
Core.split(des, hsv);
Mat v = hsv.get(2); //gets the grey scale version
Imgcodecs.imwrite("/Users/Lisa-Maria/Documents/CapturedImages/B&Wpic.jpg", v); //only writes mats
CLAHE clahe = Imgproc.createCLAHE(2.0, new Size(8,8) ); //2.0, new Size(8,8)
clahe.apply(v,v);
// Imgproc.GaussianBlur(v, v, new Size(9,9), 3); //adds left pupil boundary and random circle on 'a'
// Imgproc.GaussianBlur(v, v, new Size(9,9), 13); //adds right outer iris boundary and random circle on 'a'
Imgproc.GaussianBlur(v, v, new Size(9,9), 7); //adds left outer iris boundary and random circle on left by hair
// Imgproc.GaussianBlur(v, v, new Size(7,7), 15);
Core.addWeighted(v, 1.5, v, -0.5, 0, v);
Imgcodecs.imwrite("/Users/.../after.jpg", v); //only writes mats
if (v != null) {
Mat circles = new Mat();
Imgproc.HoughCircles( v, circles, Imgproc.CV_HOUGH_GRADIENT, 2, v.rows(), 100, 20, 20, 200 );
List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
System.out.println("circles.cols() " + circles.cols());
if(circles.cols() > 0) {
System.out.println("1");
for (int x = 0; x < circles.cols(); x++) {
System.out.println("2");
double vCircle[] = circles.get(0, x);
if(vCircle == null) {
break;
}
Point pt = new Point(Math.round(vCircle[0]), Math.round(vCircle[1]));
int radius = (int) Math.round(vCircle[2]);
//draw the found circle
Imgproc.circle(v, pt, radius, new Scalar(255,0,0),2); //newimg
//Imgproc.circle(des, pt, radius/3, new Scalar(225,0,0),2); //pupil
Imgcodecs.imwrite("/Users/.../Houghpic.jpg", v); //newimg
//draw the mask: white circle on black background
// Mat mask = new Mat( new Size( des.cols(), des.rows() ), CvType.CV_8UC1 );
// Imgproc.circle(mask, pt, radius, new Scalar(255,0,0),2);
// des.copyTo(des,mask);
// Imgcodecs.imwrite("/Users/..../mask.jpg", des); //newimg
Imgproc.logPolar(des, norm, pt, radius, Imgproc.WARP_FILL_OUTLIERS);
Imgcodecs.imwrite("/Users/..../Normalised.jpg",norm);
}
}
}
}
Результат: фото
1 ответ
После обсуждения в комментариях я публикую общий ответ с некоторыми результатами, полученными на худшем изображении, загруженном ОП.
Примечание: код, который я публикую, написан на Python, так как он самый быстрый для меня
Шаг 1. Когда вы попросите обрезать изображение, чтобы сфокусироваться только на глазах, вы можете захотеть взглянуть на Распознавание лиц. Поскольку изображение по сути требует только найти глаза, я сделал следующее:
eye_cascade = cv2.CascadeClassifier('haarcascade_eye.xml')
eyes = eye_cascade.detectMultiScale(v) // v is the value channel of the HSV image
// The results "eyes" gives you the dimensions of the rectangle where the eyes are detected as [x, y, w, h]
// Just for drawing
cv2.rectangle(v, (x1, y1), (x1+w1, y1+h1), (0, 255, 0), 2)
cv2.rectangle(v, (x2, y2), (x2+w2, y2+h2), (0, 255, 0), 2)
Теперь, когда у вас есть ограничивающие прямоугольники, вы можете обрезать прямоугольники из изображения следующим образом:
crop_eye1 = v[y1:y1+h1, x1:x1+w1]
crop_eye2 = v[y2:y2+h2, x2:x2+w2]
После того, как вы получите прямоугольники, я бы посоветовал изучить различные цветовые пространства вместо RGB/BGR, HSV/Lab/Luv в частности.
Поскольку компоненты R, G и B цвета объекта в цифровом изображении коррелируют с количеством света, попадающего на объект, и, следовательно, друг с другом, описания изображений в терминах этих компонентов затрудняют распознавание объектов. Описания с точки зрения оттенка / яркости / цветности или оттенка / яркости / насыщенности часто более актуальны
Затем, когда у вас есть глаза, пора выровнять контраст изображения, однако я предлагаю использовать CLAHE и поиграть с параметрами для clipLimit
а также tileGridSize
, Вот код, который я реализовал некоторое время назад в Java:
private static Mat clahe(Mat image, int ClipLimit, Size size){
CLAHE clahe = Imgproc.createCLAHE();
clahe.setClipLimit(ClipLimit);
clahe.setTilesGridSize(size);
Mat dest_image = new Mat();
clahe.apply(image, dest_image);
return dest_image;
}
Как только вы будете удовлетворены, вы должны сделать изображение более четким, чтобы HoughCircle был устойчивым. Вы должны посмотреть на нерезкую маску. Вот код на Java для UnsharpMask, который я реализовал на Java:
private static Mat unsharpMask(Mat input_image, Size size, double sigma){
// Make sure the {input_image} is gray.
Mat sharpend_image = new Mat(input_image.rows(), input_image.cols(), input_image.type());
Mat Blurred_image = new Mat(input_image.rows(), input_image.cols(), input_image.type());
Imgproc.GaussianBlur(input_image, Blurred_image, size, sigma);
Core.addWeighted(input_image, 2.0D, Blurred_image, -1.0D, 0.0D, sharpened_image);
return sharpened_image;
}
В качестве альтернативы, вы можете использовать двусторонний фильтр, сглаживающий края, или прочитать его для определения собственного ядра для повышения резкости изображения. Надеюсь, это поможет и удачи!