Функция addWeighted
не будет работать, поскольку она будет использовать одно и то же значение альфа-канала для всех пикселей. Чтобы сделать именно то, что вы говорите, чтобы заменить только непрозрачные значения в фоновом режиме, вы можете создать для этого небольшую функцию, например:
cv::Mat blending(cv::Mat& overlay, cv::Mat& background){
//must have same size for this to work
assert(overlay.cols == background.cols && overlay.rows == background.rows);
cv::Mat result = background.clone();
for (int i = 0; i < result.rows; i++){
for (int j = 0; j < result.cols; j++){
cv::Vec4b pix = overlay.at<cv::Vec4b>(i,j);
if (pix[3] == 0){
result.at<cv::Vec3b>(i,j) = cv::Vec3b(pix[0], pix[1], pix[2]);
}
}
}
return result;
}
Я не уверен, что прозрачное значение в opencv равно 0 или 255, поэтому измените его соответствующим образом.... Я думаю, что это 0 для непрозрачного и 255 для полностью прозрачного.
Если вы хотите использовать значение альфа-канала в качестве скорости смешивания, то немного измените его на это:
cv::Mat blending(cv::Mat& overlay, cv::Mat& background){
//must have same size for this to work
assert(overlay.cols == background.cols && overlay.rows == background.rows);
cv::Mat result = background.clone();
for (int i = 0; i < result.rows; i++){
for (int j = 0; j < result.cols; j++){
cv::Vec4b pix = overlay.at<cv::Vec4b>(i,j);
double alphaRate = 1.0 - pix[3]/255.0;
result.at<cv::Vec3b>(i,j) = (1.0 - alphaRate) * cv::Vec3b(pix[0], pix[1], pix[2]) + result.at<cv::Vec3b>(i,j) * alphaRate;
}
}
return result;
}
Извините за код на C++, а не на JAVA, но я думаю, что вы можете получить представление. В основном это просто цикл в пикселях и изменение пикселей в копии фона на пиксели наложения, если они не прозрачны.
* ИЗМЕНИТЬ *
Я отвечу на ваш комментарий этим редактированием, так как это может занять место. Проблема в том, как работает матрица OpenCV. Для изображения с альфой данные организованы в виде массива типа BGRA BGRA .... BGRA
, а основные операции, такие как сложение, умножение и т. д., работают в матрицах с одинаковыми размерами..... всегда можно попробовать разделить матрицу с помощью разделения ( это перезапишет матрицу, так что это может быть медленным), затем измените альфа-канал на двойной (опять же, перепишите), а затем выполните умножение и добавление матриц. Это должно быть быстрее, так как OpenCV оптимизирует эти функции.... также вы можете сделать это в графическом процессоре....
Что-то вроде этого:
cv::Mat blending(cv::Mat& overlay, cv::Mat& background){
std::vector<cv::Mat> channels;
cv::split(overlay, channels);
channels[3].convertTo(channels[3], CV_64F, 1.0/255.0);
cv::Mat newOverlay, result;
cv::merge(channels, newOverlay);
result = newOverlay * channels[3] + ((1 - channels[3]) * background);
return result;
}
Не уверен, позволяет ли OpenCV CV_8U
умножать CV_64F
, будет ли это быстрее или нет.... но может быть.
Кроме того, те, у которых есть циклы, не имеют проблем с потоками, поэтому их можно оптимизировать... выполнение этого в режиме выпуска также значительно увеличит скорость, поскольку функция .at
OpenCV выполняет несколько утверждений... что в режиме выпуска нет Выполнено. Не уверен, что это можно изменить в JAVA...
09.05.2016
add()
,subtract()
,multiply()
и т. д.? 09.05.2016