Недавно на Хабре была опубликована статья со съёмками ночного неба «Ночная жизнь неба или в поисках Персеид». Но самих метеоров авторы не смогли обнаружить из-за большого количества спутников, которые в данном случае являются ложными объектами. Я не смог пройти мимо, решил обработать видео, и посмотреть, есть ли на нём Персеиды или нет.
Для начала я построил видео без фона звёзд при помощи инструмента BackgroundSubtractorMOG2 из OpenCV. Для подавления «шумовых» срабатываний, обусловленных сжатием видео, к каждому кадру применил усредняющий фильтр с окном 3×3, а к изображению движущихся объектов применил операцию opening, для подавления мелких срабатываний. Без предварительной фильтрации на карте движения отчётливо просматривались «шашечки». Первые три кадра убрал из обработки, т.к. алгоритм BackgroundSubtractorMOG2 на них ещё не накопил информацию о движении.
int generate_meteor_lines() { cv::VideoCapture cap; cap.open(videoname); if(!cap.isOpened()) { printf("can not open video filen"); return -1; } cv::namedWindow("foreground image", cv::WINDOW_NORMAL); cv::BackgroundSubtractorMOG2 bg_model; double learning_rate = 0.1; bg_model.setBool("detectShadows", false); bg_model.setDouble("backgroundRatio", 0.95); bg_model.setInt("history", 5); bg_model.setInt("fVarInit", 20); cv::Mat img, fgmask, fgimg; std::cerr << "n"; for(int frames_count = 0;; ++frames_count) { cap >> img; if(img.empty()) { break; } cv::blur(img, img, cv::Size(3, 3)); if(fgimg.empty()) { fgimg.create(img.size(), img.type()); } bg_model(img, fgmask, learning_rate); fgimg = cv::Scalar::all(0); img.copyTo(fgimg, fgmask); cv::threshold(fgimg, fgimg, 20, 255, cv::THRESH_BINARY); cv::Mat mask(cv::Mat::ones(3, 3, CV_8UC1)); mask.at(0, 0) = 0; mask.at(2, 0) = 0; mask.at(0, 2) = 0; mask.at(2, 2) = 0; cv::erode(fgimg, fgimg, mask); cv::dilate(fgimg, fgimg, mask); if(frames_count > 3) { detect_lines(fgimg); } imshow("foreground image", fgimg); std::cerr << "Frame ##" << frames_count << "n"; char k = (char)cv::waitKey(30); if(k == 27) { break; } } return 0; }
После просмотра стало понятно, что метеоры на видео есть, но их скорость много выше (согласно википедии, видимая скорость метеора из Персеид около 59 км/c), чем скорость спутников, и они проявляютса на одном-двух последовательных кадрах в виде короткой линии. Так что глаз просто не успевает среагировать на них на фоне ярких звёзд.
Далее, чтобы было удобнее искать метеоры, я сделал простейший детектор на основе преобразования Хафа, который подсвечивал метеоры на оригинальном видео.
std::vector detect_lines(cv::Mat& img) { cv::Mat coi; std::vector lines; cv::extractChannel(img, coi, 0); double rho_res = 1; double theta_res = CV_PI / 180; double ithreshold = 50; double minLinLength = 50; double maxLineGap = 2; cv::HoughLinesP(coi, lines, rho_res, theta_res, ithreshold, minLinLength, maxLineGap); draw_line_circles(lines, img); return lines; }
И даже с подсветкой трудно понять, был ли метеор или нет. Только если просматривать в режиме стоп кадров. Но после наложения всех следов метеоров на фоновое изображение мы имеем более целостную картину. Видно, что большая часть объектов «вылетает» из правой нижней части изображения.
Но действительно ли там и есть созвездие Персея?
Я не сильный знаток звёздного неба, поэтому я сделал снимок экрана из программы «Stellarium» с Персеидами в центре. Выбрал вручную некоторое количество звёзд, которые смог сопоставить на «усреднённом» фоновом изображении из видео и снимком экрана из Стеллариума. По координатам связующих точек построил двумерный полином третьей степени и пересчитал положение источника Персеид с опорного изображения на фон от видео. Источник Персеид, к моему удивлению, как раз и оказался в правом нижнем углу.
Так что, авторы статьи не зря искали. Персеиды были!
Источник