Функция 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, но я подумайте, что вы можете получить представление. В принципе, это всего лишь петля в пикселях и изменение пикселей в копии фона на фоне наложения, если они не прозрачны.
* EDIT *
Я отвечу на ваш комментарий с этим редактированием, так как это может занять место. Проблема заключается в том, как работает матрица OpenCV. Для изображения с альфой данные организованы как массив, такой как BGRA BGRA .... BGRA
, и основные операции, такие как добавление, умножение и т. Д., Работают в матрицах с одинаковыми размерами ..... вы всегда можете попытаться отделить матрицу с помощью split (это запишет матрицу так, чтобы она была медленной), затем измените альфа-канал на двойной (опять же переписать), а затем произведите умножение и добавление матриц. Он должен быть быстрее, так как 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
, или если это будет быстрее или нет ... но может быть.
Кроме того, те, у которых есть петли, не имеют проблем в потоках, поэтому их можно оптимизировать ... запуск этого режима освобождения значительно увеличит скорость, так как функция OpenCV .at
делает несколько утверждений .... что в режим освобождения не выполняется. Не уверен, что это может быть изменение в JAVA, хотя ...
Проверить [это] (http://stackoverflow.com/a/32481105/5008845), вы должны получить идею – Miki