Как стать автором
Обновить
7
0
Игорь Бикинеев @websiteam

Пользователь

Отправить сообщение
Еще один полезный сервис — Random Material Generator
И, кстати, что насчет молочной каши и омлета, этих простых и вкусных блюд? Из-за присутствия в рецепте молока долго хранить их не рекомендуется, поэтому мультиварка небольшого объема подойдет лучше всего. До появления мультиварки и то и другое готовили очень редко. Сейчас часто встречается на столе. Что может быть проще приготовления рисовой или овсяной каши в мультиварке? — В пропорции 4:1 налить молоко и насыпать крупу, бросить кусок сливочного масла, соль, сахар. Закрыть крышку и поставить на режим «Молочная каша». Режим в Панасонике автоматический — выключится сама. Молоко ни разу не убегало. Омлет толщиной 2-3 см ни разу не пригорал.
Уже, кажется, четвертый год пользуюсь Panasonic SR-TMH10 объемом 2,5 литра. Покупал осознанно именно такого объема на семью из 3-х человек — всегда свежая пища. На мой взгляд, основное преимущество мультиварок — свежая и здоровая пища при минимальном участии человека в процессе готовки. Супы готовлю за 10-15 минут — обжарка овощей (лук, морковка, свекла и т.п.) на режиме «выпечка». Одновременно чищу пару картофелин, достаю из морозилки остальные ингредиенты (разложенное на порционные куски и замороженное мясо, овощные смеси и т.п.). Бросаю все в мультиварку, заливаю водой, соль, перец… Ставлю на режим «тушение» на 3-5 часов и занимаюсь своими делами, так как больше моего участия не требуется. Готовится все одновременно, ничего не разваривается. В итоге всегда свежеприготовленная еда. Готовить каждый день не надоедает, так как на все, повторюсь, тратится 10-15 минут.
Вот как я это делаю в своем приложении (Java):
private void putWaterMark(Mat alpha){
	String logo = _applicationName;
	String subLogo = "Free version";
	double fontScale = 1;
	double maxFontScale = 15;
	int thickness = 7;
	int [] baseline = {0};
	// начало текста по горизонтали
	double x = Math.random() * alpha.cols()/10+15;

	// начало текста по вертикали
	double y1 = alpha.rows() / 10.;
	double y2 = alpha.rows() * 0.9;
	double y = y1 + Math.random() * (y2 - y1); 
		
	Point beginLogo = new Point(x,y);
		
	// максимальная ширина текста
	int maxLength = alpha.cols() - (int) beginLogo.x;
		
	// подбор размера фонта под ширину текста:
	Size textsize = new Size(100,100);
	for (double d=maxFontScale; d>0; d = d - 0.5){
		textsize = Core.getTextSize(logo, Core.FONT_HERSHEY_COMPLEX, d, thickness, baseline);
		if (textsize.width < maxLength) {
			fontScale = d;
			break;
		}
	}
		
	Core.putText(alpha, logo, beginLogo, Core.FONT_HERSHEY_COMPLEX, fontScale, new Scalar(255), thickness);
	beginLogo.y = beginLogo.y + textsize.height;
	Core.putText(alpha, subLogo, beginLogo, Core.FONT_HERSHEY_COMPLEX, fontScale/2, new Scalar(255), thickness-3);
}


Я использую в приложении библиотеку OpenCV, поэтому она же применена здесь при наложении текста.
На входе пустое изображение (Mat alpha) того же размера как исходное, только в градациях серого (однобайтное). На выходе на него наложен требуемый текст. И сейчас это изображение можно накладывать на исходное. Как — зависит от конкретной реализации, вот у меня здесь есть немного про наложение картинок.
Вот, кстати результат наложения:
image
Так как по долгу службы связан с поверкой приборов учета воды и тепла — пара предложений, связанных с периодической поверкой приборов.
1. Добавить напоминание при подходе даты следующей поверки прибора учета. Понадобится пара дополнительных полей для каждого прибора — дата последней поверки и межповерочный интервал.
2. Возможно, пользователям Вашего сервиса удастся немного сэкономить при подаче коллективной заявки на поверку приборов учета воды. Во многих крупных и средних городах России сейчас организована поверка квартирных водосчетчиков без их демонтажа с трубопровода — поверитель выезжает по заявке на указанный адрес. Большинство государственных поверочных центров (ЦСМ) имеют гибкую систему цен на поверку водосчетчиков, не говоря уже о частных поверочных лабораториях. Если с помощью Вашего сервиса удастся скооперироваться жителям одного или нескольких близлежащих домов — они охотно снизят цену поверки до минимальной.
И, кстати, спасибо за тест. :)

Вам спасибо за ценные советы. Дополнил статью новыми тестами.
Попробую дать развернутый ответ.
Во-первых, вот этот код не работает.
В приведенном мною выше примере код

double[] matPix = mat.get(i, j);

работает для матрицы любого типа. Если же мы создадим массив типа double и попробуем туда скопировать данные матрицы типа CV_8U

double[] buff = new double[size];
mat.get(0, 0, buff);

то произойдет исключение. Залез в исходники OpenCV — все верно, проверяется, правильного ли типа матрица, если нет — возбуждается исключение. Попробовал объявить нужный тип буфера — как сказано здесь. Переписал вышеприведенный код на этот:

int size = mat.cols();
for (int i=0; i<mat.rows(); i++){
	byte[] matPix = new byte[size];
	byte[] topPix = new byte[size];
	mat.get(i, 0, matPix);
	top.get(i, 0, topPix);
	for (int j=0; j<size; j++) {
		if (matPix[j]+topPix[j]>255){
			matPix[j] = (byte) 255;
		} else {
			matPix[j] = (byte) ((255 * matPix[j]) / (256 - topPix[j]));
		}
	}
	mat.put(i, 0, matPix);
}

Все работает, но вместо эффекта Pencil sketch у меня получается кадр из фильма «Хищник». Почему так? — byte[] в Java — массив со знаком. В OpenCV get и put с массивами типа uchar (пока?) не работают. Но этот оптимизированный код работает быстро. У меня получилось 60, 50 и 50 миллисекунд против 30, 20 и 20 неоптимизированного NDK. Создание еще одного (двух в моем случае) буферных массивов типа char, преобразование данных, работа с ними, затем обратное преобразование возможно даст эффект, но, по-моему, использование NDK для этих целей проще.
Сравнивать скорость у девайсов в данном случае некорректно, так как тестировались копии картинки, уменьшенные пропорционально размеру экранов устройств.
В выходные постараюсь проверить. Самому интересно.
Я согласен. В некритичных случаях приведенный Вами пример вполне подходит.
Вот, например, существенно более быстрый способ: ровно одно копирование.

Верно. Только это удвоение (утроение в данном примере) используемой памяти. А если все операции происходят с 13 MP картинкой?
Нет. И, как я понимаю, он только с 3-го Андроида работает?
Я так понял что аналог нейтивному коду — это закоментированный код?

Совершенно верно.
Если же нужно обработать именно Mat, тогда очевидно лучшим решением будет использовать предоставляемые методы, или сконвертировать его в Bitmap и использовать упомянутые методы

А что Вы подразумеваете под предоставляемыми методами? Методы OpenCV? Так я их и использую в 90% случаев и только там, где нет подходящего метода, пишу свой. Был, кстати, еще случай, когда приложение вылетало при применении стандартной функции OpenCV — поэлементного умножения матриц. Вот тут тоже пришлось переписать ее на C++.
Что касается преобразований Mat -> Bitmap и обратно, то это очень затратные функции и по времени и по памяти.
Там их заменяют
uchar matPix = mat.at<uchar>(i, j);
mat.at<uchar>(i, j) = matPix;
Именно сам алгоритм. Вот как то так:
public static boolean ColorDodgeGray(Mat mat, Mat top){
		
		Log.i(TAG,"ColorDodgeGray BEGIN");
		
		NativeUtils.nativeColorDodgeGray(mat.getNativeObjAddr(), top.getNativeObjAddr());
		
		/*for (int i=0; i<mat.rows(); i++){
			for (int j=0; j<mat.cols(); j++) {
				double[] matPix = mat.get(i, j);
				double[] topPix = top.get(i, j);
				if (matPix[0]+topPix[0]>255){
					matPix[0] = 255.;
				} else {
					matPix[0] = (255. * matPix[0]) / (256. - topPix[0]);
				}
				mat.put(i, j, matPix);
			}	
		}*/
		Log.i(TAG,"ColorDodgeGray END");
		return true;
	}

Информация

В рейтинге
Не участвует
Откуда
Киров (Кировская обл.), Кировская обл., Россия
Дата рождения
Зарегистрирован
Активность