Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 05.07.2017, 14:45   #1
Mukudori
Пользователь
 
Регистрация: 05.07.2017
Сообщений: 24
По умолчанию OpenCV и оценка качества изображений

Передо мной стоит задача оценить качество изображений.

Моя задача решена Здесь, на языке python, где и описана цель, для чего мне это нужно. Но возникают 2 проблемы.

Первая проблема в том, что я никогда не работал на питоне и для целевой платформы он не подходит, а на С++ я этот код перевести не могу из за существенного различия в синтаксисе.

Вторая проблема заключается в объективности этого метода. Я читал, что применение методов типа cv::Laplacian не обеспечивает объективную оценку, а параметры изображений нужно подгонять каждому индивидуальные, так как при изменении контрастности выдаются совершенно другие результаты. Но так как я не смог в точности перевести предложенный код на С++ я не могу сказать насколько хорошо он работает.

Прошу помочь мне советом или переводом предложенного в статье кода.
Mukudori вне форума Ответить с цитированием
Старый 05.07.2017, 14:55   #2
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Интересно на эту тему поговорить, у меня сейчас вопрос оценить размытость астро-фото.
Вот такую чтуку применил, но, похоже она для точечных источников (типа звезд). Хотя, с любыми картинками - менее размытая дает меньшее число (но вот сами числа, для разных объектов разные, для звезд это 0.1, для луны от 0.8 до 1.1, смотря какая часть луны).

Код:
cv::Mat utility::opencv::algos::get_FWHM(const cv::Mat &src)
{
    //https://en.wikipedia.org/wiki/Full_width_at_half_maximum
    const auto static coef = 2 * sqrt(2 * log(2));
    cv::Mat mean, stddev;
    cv::meanStdDev(src, mean, stddev);
    stddev *= coef;

    //https://sourceforge.net/projects/astrofocuser/?source=typ_redirect
    stddev.forEach<double>([](double& v, const int*)
    {
       v = 2 * sqrt(v / M_PI);
    });

    return stddev;
}
Статья тут
https://ru.wikipedia.org/wiki/%D0%9F...B8%D0%BD%D0%B0


...перевел ваш питон пример, помоему так (источник нужен серый):

Код:
cv::Mat utility::opencv::algos::get_Blureness(const cv::Mat &src)
{
    cv::Mat dest;
    cv::Laplacian(src, dest, src.type());
    return get_FWHM(dest);
}
Числа теперь и для звезд и для луны примерно в 1 промежутке, и чем больше число, тем меньше размытость.
Для Луны реально круто работает - спасибо. Для звезд чуть хуже - там шумы как-то мешают, нек. более резкие фотки получили меньшее число, из-за большего шума.

Для серий думаю такой подход - у всей серии находим мин/макс блура, и выбираем фотки, входящие в топ 30% интервала.

Последний раз редактировалось alexzk; 05.07.2017 в 15:40.
alexzk вне форума Ответить с цитированием
Старый 05.07.2017, 16:05   #3
Mukudori
Пользователь
 
Регистрация: 05.07.2017
Сообщений: 24
По умолчанию

Цитата:
Сообщение от alexzk Посмотреть сообщение

...перевел ваш питон пример, помоему так (источник нужен серый):

Код:
cv::Mat utility::opencv::algos::get_Blureness(const cv::Mat &src)
{
    cv::Mat dest;
    cv::Laplacian(src, dest, src.type());
    return get_FWHM(dest);
}
Изображение я сразу считываю в матрицу с параметром "CV_LOAD_IMAGE_GRAYSCALE". У вас функция возвращает матрицу, а как из этой матрицы числовое значение взять? Это сумма яркостей?

Код:
double MatSum(Mat img)
	{
		double sum = 0;
		for (int j = 0; j < img.rows; j++)
		{
			for (int i = 0; i < img.cols; i++)
			{
				sum += img.at<uchar>(j, i);
			}
		}

		return sum;
	}
Mukudori вне форума Ответить с цитированием
Старый 05.07.2017, 16:16   #4
Mukudori
Пользователь
 
Регистрация: 05.07.2017
Сообщений: 24
По умолчанию

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

пример 64-83- 1000

мой результат 134-151-254


Возможно в различиях виновато то, что я тупо копировал представленные фото и обрезал рамочки

Последний раз редактировалось Mukudori; 05.07.2017 в 16:20.
Mukudori вне форума Ответить с цитированием
Старый 05.07.2017, 16:21   #5
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Входная матрица у меня серая и

Код:
 c.convertTo(c, CV_64F);// convert to double
 normalize(c, c, 0, 1, cv::NORM_MINMAX);
Ну и числа у меня ....0.21+ выходят для вполне резких фрагментов Луны, 0.237 там вообще супер картинка - все детали просматриваются в центре.

Там у меня еще фрагмент есть

Код:
 stddev.forEach<double>([](double& v, const int*)
    {
       v = 2 * sqrt(v / M_PI);
    });
помоему он астрономический - переводит в секунды дуги, но не уверен.

Вобще сущность метода
1. Сделать лапласиан
2. Расчитать по лапласиану среднеквадратическое отклонение.

Для серого изображения, в результате верный нулевой член матрицы (double, для исходного формата double):
Код:
precalcs.blureness = algos::get_Blureness(*mat).at<decltype (precalcs.blureness)>(0);

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

Последний раз редактировалось alexzk; 05.07.2017 в 16:25.
alexzk вне форума Ответить с цитированием
Старый 05.07.2017, 16:27   #6
Cuprum5
Форумчанин
 
Регистрация: 09.05.2017
Сообщений: 734
По умолчанию

Цитата:
Сообщение от Mukudori Посмотреть сообщение
Первая проблема в том, что я никогда не работал на питоне и для целевой платформы он не подходит, а на С++ я этот код перевести не могу из за существенного различия в синтаксисе.
- наверное не из-за различия в синтаксисе, а в то что это закрытый метод. Автор просто там не дал подробное описание его, так?
Напишу программу на C++ и Asm для AVR. Черчение: sergeisky@yahoo.com.
Cuprum5 вне форума Ответить с цитированием
Старый 05.07.2017, 16:30   #7
Mukudori
Пользователь
 
Регистрация: 05.07.2017
Сообщений: 24
По умолчанию

Цитата:
Сообщение от Cuprum5 Посмотреть сообщение
- наверное не из-за различия в синтаксисе, а в то что это закрытый метод. Автор просто там не дал подробное описание его, так?
И это тоже. Для меня большая загадка как он получил эти числа, так как в первую очередь я обратил внимание на то, что не выполняется никаких вычислительных операций, кроме использования метода Лапласа
Mukudori вне форума Ответить с цитированием
Старый 05.07.2017, 16:35   #8
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Ну совсем точный перевод, мне кажется таким

Код:
cv::Laplacian(src, dest, src.type());
cv::Mat mean, stddev;
 cv::meanStdDev(src, mean, stddev);

auto res = stddev.at<double>(0);
А сами значения чисел будут сильно зависить от формата исходной матрицы, если она U8C1, то и результат будет таким, но в отличие от питона, в С++ нет авт. расширения типа, так что ваша 1000 в питоне обрежится до 1000 % 256 в С++. Поэтому и говорю - пользуйте дабл с нормализацией.
alexzk вне форума Ответить с цитированием
Старый 05.07.2017, 16:44   #9
Mukudori
Пользователь
 
Регистрация: 05.07.2017
Сообщений: 24
По умолчанию

мне не совсем понятно как работает эта конструкция:

Код:
 stddev.forEach<double>([](double& v, const int*)
    {
       v = 2 * sqrt(v / M_PI);
    });
с помощью этого кода значения в переменной res фигурируют между 40 и 60(из тех что я тестировал через uchar)

Код:
double getBlurPyth(char* url)
{
	
	Mat image = imread(url, CV_LOAD_IMAGE_GRAYSCALE);
	Mat dest;
	cv::Laplacian(image, dest, image.type());
	cv::Mat mean, stddev;
	cv::meanStdDev(image, mean, stddev);

	auto res = stddev.at<double>(0);
	return res;
}
при этом если я возьму другое четкое изображение и начну искуственно накладывать фильтры размытия с помощью графического редактора, то такой код почему-то слабо реагирует на этот вид размытия, существенно изменяя значение только когда совсем ничего не видно

Последний раз редактировалось Mukudori; 05.07.2017 в 16:50.
Mukudori вне форума Ответить с цитированием
Старый 05.07.2017, 16:54   #10
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Код:
double getBlurPyth(char* url)
{
	
	Mat image = imread(url, CV_LOAD_IMAGE_GRAYSCALE);
        image.convertTo(image, CV_64F);// convert to double
        normalize(image, image, 0, 1, cv::NORM_MINMAX);
	Mat dest;
	cv::Laplacian(image, dest, image.type());
	cv::Mat mean, stddev;
	cv::meanStdDev(image, mean, stddev);

	auto res = stddev.at<double>(0);
	return res;
}
Потому что вы точность теряете, и что значит слабо? - вот в таком виде реакция будет в районе 3-4 знака после запятой, 1-2 реагируют, когда совсем ниче не видно.
alexzk вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Оценка потребляемой памяти и оценка времени выполнения. halcyon Общие вопросы C/C++ 0 22.03.2015 13:42
Качества программиста Makarrrr Свободное общение 12 03.02.2014 22:48
Оценка качества ГПСЧ Veryn4ik1993 Помощь студентам 13 02.01.2014 13:15
WPF + C# Подгрузка изображений в память, без блокирования файлов изображений fezilk25 C# (си шарп) 0 02.01.2014 11:28