Используя openCV, вы можете сделать следующее:
- масштабирует оба исходных изображения (1 и 2) с коэффициентом 0,5. Оба изображения теперь находятся в диапазоне [0..127]
- смещение изображения 1 на 128. Теперь оно находится в диапазоне [128..255]
- вычесть изображение 2 из изображения 1
Таким образом, преобразование диапазона не требуется, и результат полностью масштабируется до 8 бит. Используйте cvConvertScale
для первых двух операций.
Примерно так:
//...
cvConvertScale(src1, tmp1, 0.5, 128);
cvConvertScale(src2, tmp2, 0.5, 0);
cvSub(tmp1, tmp2, dst);
EDIT:
На ваш комментарий о потере информации (точности) вы правы, но вы всегда делаете это при делении с использованием целочисленной математики. И масштабирование в вашем случае это просто так. Просто думайте об этом как о смещении всех битов вправо на одно место. Таким образом, последний бит информации теряется.
С другой стороны, порядок применяемых операций также важен. Делив на 2, вы вводите ошибку округления (или усечения) 0.5
для каждого пикселя. Если вы масштабируете оба входных изображения до их вычитания, ошибка округления в сумме составляет 1.0
. Это проявляется в результирующем изображении, когда некоторые пиксели смещены на 1 по сравнению с результатом, который вы получите при использовании исходного подхода и подхода Александера. Но это компромисс для более простого решения без расширения изображения до 16-битной или с плавающей запятой.
См. Этот пример:
действительные числа:
(200 - 101) / 2 = 99/2 = 49,5
Решение Александера (целочисленная математика):
(200 - 101) / 2 = 99/2 = 49
мое решение (целочисленная математика):
(200/2) - (101/2) = 100 - 50 = 50