Сначала уточню по вычитанию битовых изображений pixLeft[] и pixRight[]:
Логически раскрашиваем разностное изображение pixRes[] следующим образом:(псевдокод аля Паскаль)
Это необходимо делать при частичном перекрытии объектом самого себя, что не исключено.
if (pixLeft[i,j] = 0) and pixRight[i,j] = 0 then pixRes[i,j] := clWhite;
if (pixLeft[i,j] = 1) and pixRight[i,j] = 1 then pixRes[i,j] := clBlack;
if (pixLeft[i,j] > pixRight[i,j]) then pixRes[i,j] := clRed;
if (pixLeft[i,j] < pixRight[i,j]) then pixRes[i,j] := clBlue;
cl* - условные "цвета" пикселей разностного изображения.
Определение центра тяжести или геометрическиго центра, что для битовых одно и то же.Для "компактных" объектов может подойти примитивный способ:
X := (Xmin + Xmax)/2;
Y := (Ymin + Ymax)/2;
Но лучше, через дискретное интегрирование:
Координаты ц.т. изображений L и R находим как сумму координат поделенную на число точек:
cntL: integer; // число точек "левого" объекта - площадь в пикселях
cntR: integer; // число точек "правого" объекта - площадь в пикселях
crdLX, crdRX: integer; // координаты ц.т. "левого" объекта, pix
crdLY, crdRY: integer; // координаты ц.т. "правого" объекта, pix
for i := 0 to W-1
for j := 0 to H-1 do begin
if (pixRes[i,j] = clRed) or (pixRes[i,j] = clBlack) then begin
crdLX := crdLX + i + 1; crdLY := crdLY + j + 1;
Inc(cntL);
end;
if (pixRes[i,j] = clBlue) or (pixRes[i,j] = clBlack) then begin
crdRX := crdRX + i + 1; crdRY := crdRY + j + 1;
Inc(cntR);
end;
end;
if cnt* > 0 then
crd* := crd* / cnt*; // для приведения ц.т. в масштаб изображения
***
Пример детектирования расстояния
Shift - установленный сдвиг
Calc - вычисленный по алгоритму выше.

P.S.
ТС задал явные ограничения на мощность MCU и свои возможности, потому предлагается легкий алгоритм, как для MCU, так и для него.
Сложность пропорциональна N.

***
Пример графика заданного и найденного сдвигов
Наблюдаем хорошую линейность и точность до 60 pix ( после 60 pix - выход за границы и вычисления некорректны )