И, кстати, что насчет молочной каши и омлета, этих простых и вкусных блюд? Из-за присутствия в рецепте молока долго хранить их не рекомендуется, поэтому мультиварка небольшого объема подойдет лучше всего. До появления мультиварки и то и другое готовили очень редко. Сейчас часто встречается на столе. Что может быть проще приготовления рисовой или овсяной каши в мультиварке? — В пропорции 4:1 налить молоко и насыпать крупу, бросить кусок сливочного масла, соль, сахар. Закрыть крышку и поставить на режим «Молочная каша». Режим в Панасонике автоматический — выключится сама. Молоко ни разу не убегало. Омлет толщиной 2-3 см ни разу не пригорал.
Уже, кажется, четвертый год пользуюсь Panasonic SR-TMH10 объемом 2,5 литра. Покупал осознанно именно такого объема на семью из 3-х человек — всегда свежая пища. На мой взгляд, основное преимущество мультиварок — свежая и здоровая пища при минимальном участии человека в процессе готовки. Супы готовлю за 10-15 минут — обжарка овощей (лук, морковка, свекла и т.п.) на режиме «выпечка». Одновременно чищу пару картофелин, достаю из морозилки остальные ингредиенты (разложенное на порционные куски и замороженное мясо, овощные смеси и т.п.). Бросаю все в мультиварку, заливаю водой, соль, перец… Ставлю на режим «тушение» на 3-5 часов и занимаюсь своими делами, так как больше моего участия не требуется. Готовится все одновременно, ничего не разваривается. В итоге всегда свежеприготовленная еда. Готовить каждый день не надоедает, так как на все, повторюсь, тратится 10-15 минут.
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) того же размера как исходное, только в градациях серого (однобайтное). На выходе на него наложен требуемый текст. И сейчас это изображение можно накладывать на исходное. Как — зависит от конкретной реализации, вот у меня здесь есть немного про наложение картинок.
Вот, кстати результат наложения:
Так как по долгу службы связан с поверкой приборов учета воды и тепла — пара предложений, связанных с периодической поверкой приборов.
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 для этих целей проще.
Сравнивать скорость у девайсов в данном случае некорректно, так как тестировались копии картинки, уменьшенные пропорционально размеру экранов устройств.
Я так понял что аналог нейтивному коду — это закоментированный код?
Совершенно верно.
Если же нужно обработать именно Mat, тогда очевидно лучшим решением будет использовать предоставляемые методы, или сконвертировать его в Bitmap и использовать упомянутые методы
А что Вы подразумеваете под предоставляемыми методами? Методы OpenCV? Так я их и использую в 90% случаев и только там, где нет подходящего метода, пишу свой. Был, кстати, еще случай, когда приложение вылетало при применении стандартной функции OpenCV — поэлементного умножения матриц. Вот тут тоже пришлось переписать ее на C++.
Что касается преобразований Mat -> Bitmap и обратно, то это очень затратные функции и по времени и по памяти.
Я использую в приложении библиотеку OpenCV, поэтому она же применена здесь при наложении текста.
На входе пустое изображение (Mat alpha) того же размера как исходное, только в градациях серого (однобайтное). На выходе на него наложен требуемый текст. И сейчас это изображение можно накладывать на исходное. Как — зависит от конкретной реализации, вот у меня здесь есть немного про наложение картинок.
Вот, кстати результат наложения:
Вот еще пара книжек по OpenCV:
Mastering OpenCV with Practical Computer Vision Projects
OpenCV 2 Computer Vision Application Programming Cookbook
1. Добавить напоминание при подходе даты следующей поверки прибора учета. Понадобится пара дополнительных полей для каждого прибора — дата последней поверки и межповерочный интервал.
2. Возможно, пользователям Вашего сервиса удастся немного сэкономить при подаче коллективной заявки на поверку приборов учета воды. Во многих крупных и средних городах России сейчас организована поверка квартирных водосчетчиков без их демонтажа с трубопровода — поверитель выезжает по заявке на указанный адрес. Большинство государственных поверочных центров (ЦСМ) имеют гибкую систему цен на поверку водосчетчиков, не говоря уже о частных поверочных лабораториях. Если с помощью Вашего сервиса удастся скооперироваться жителям одного или нескольких близлежащих домов — они охотно снизят цену поверки до минимальной.
Вам спасибо за ценные советы. Дополнил статью новыми тестами.
Во-первых, вот этот код не работает.
В приведенном мною выше примере код
работает для матрицы любого типа. Если же мы создадим массив типа double и попробуем туда скопировать данные матрицы типа CV_8U
то произойдет исключение. Залез в исходники OpenCV — все верно, проверяется, правильного ли типа матрица, если нет — возбуждается исключение. Попробовал объявить нужный тип буфера — как сказано здесь. Переписал вышеприведенный код на этот:
Все работает, но вместо эффекта Pencil sketch у меня получается кадр из фильма «Хищник». Почему так? — byte[] в Java — массив со знаком. В OpenCV get и put с массивами типа uchar (пока?) не работают. Но этот оптимизированный код работает быстро. У меня получилось 60, 50 и 50 миллисекунд против 30, 20 и 20 неоптимизированного NDK. Создание еще одного (двух в моем случае) буферных массивов типа char, преобразование данных, работа с ними, затем обратное преобразование возможно даст эффект, но, по-моему, использование NDK для этих целей проще.
Верно. Только это удвоение (утроение в данном примере) используемой памяти. А если все операции происходят с 13 MP картинкой?
Совершенно верно.
А что Вы подразумеваете под предоставляемыми методами? Методы OpenCV? Так я их и использую в 90% случаев и только там, где нет подходящего метода, пишу свой. Был, кстати, еще случай, когда приложение вылетало при применении стандартной функции OpenCV — поэлементного умножения матриц. Вот тут тоже пришлось переписать ее на C++.
Что касается преобразований Mat -> Bitmap и обратно, то это очень затратные функции и по времени и по памяти.