N.A., слушайте, вы на ректифицированной мной стереопаре ЛМ видите нормально, форма правильная?
К сожалению, на ней сложно увидеть рельеф в силу большой стереобазы (и сильного сдвига вблизи), но то, что плохо для глаз, хорошо для точности, чем больше стереобаза, тем лучше будет разрешение по z-координате.
Если да, тогда берите список соответствий и марш считать 3D координаты. Когда закончите, убедитесь, что точки относящиеся к основанию камней лежат примерно в одной плоскости с разбросом от мин до макс 20 см. Точность ректификации проверяется элементарно по ЛМ, расстояние между движками ориентации составляет немногим меньше 4 м (в документации 4), высота отличается тоже на 15-20 см.
Если нет - тогда вам к окулисту, потому что объем ЛМ мало того, что виден нормально, так ещё и при расчетах похож на правду.
Если видите, но не верите расчетам, тогда смотрите метод ректификации ниже. Ошибок там нет, ибо это
стандартный алгоритм. Я только получил значения углов поворотов для репроекции более дубовым способом, чем это делается в opencv (зато это избавило меня от артефактов, которые я упорно получал там, это связано, возможно, с какими-то ограничениями их алгоритма), но какое значение имеет способ, которым получены необходимые преобразования? Имеет значение результат, а он говорит сам за себя - для снимков 4400x4600 расхождение в примерно 1 точку в некоторых местах - это вполне хороший результат.
Если вас не устраивает стереопара, я могу ректифицировать какую-нибудь другую, где рельеф будет виден глазами.
Во всех случаях вы можете срочно спрятать свои анаглифы, перекрыть поток красноречия, и принести извинения за потраченное мной на ваш бред время и тихо слиться.
Напоминаю, что оптическая ось проходит через 1200, 2300 для первой половины стереопары и 2500,2300 для второй, разрешение каждой из половин - 4400x4600. Разрешаю вам также добавить соответствий из той области где вы видите, по вашему мнению, более серьезные, чем 20 см, выгибы. Как закончите - расскажите нам, сколько у вас получилось. Если считаете свой метод лучше, тогда предоставляйте вашу ректификацию, ваши точки и параметры камеры для них, будем проверять.
Напоследок замечу вам, что у меня есть стереофотоаппарат, с 3D экраном, и в зависимости от параметров съемки объем может выглядеть гипертрофированным или наоборот, слабо выраженным, поэтому ваше "вижу" для анаглифов не катит. Тут ведь стереобаза больше, чем для глаз, и сами камеры иначе устроены, чем глаза.
Больше мне вам сказать нечего, остальное я буду говорить для тех, кто действительно хочет что-то выяснить, вас прошу не беспокоиться.
Как повторить репроекции для ректификации:
#define PI 3.14159265f
typedef struct
{
float cx, cy, fx, fy; // поля структуры описания камеры, cx, cy - координаты оптической оси, fx, fy - фокусные расстояния по горизонтали и вертикали
}
INTERNALS;
typedef struct
{
INTERNALS internals; // описание камеры
float ax, ay, az; // углы поворота для репроекции
}
REPROJECTION;
// функция поворота точки на угол alpha
void rotate(float &x, float &y, float alpha)
{
float nx = x * cos(alpha) - y * sin(alpha);
float ny = x * sin(alpha) + y * cos(alpha);
x = nx;
y = ny;
}
// функция репроекции снимка
void reproject(Mat *SrcImg, Mat *DstImg, REPROJECTION *Reprojection, INTERNALS *NewInternals)
{
if (!SrcImg->empty())
{
CvSize sz = SrcImg->size(); // получаем размер исходного изображения
Mat mx, my;
mx.create(sz, CV_32FC1); // создаем массивы горизонтальных и вертикальных координат на исходном изображении
my.create(sz, CV_32FC1);
for (int j = 0; j < sz.height; j++) // для каждой строки
{
for (int i = 0; i < sz.width; i++) // для каждого столбца
{
// тело цикла - преобразование координат выходного снимка в координаты на входном
float x = (i-NewInternals->cx) / NewInternals->fx;
float y = (j-NewInternals->cy) / NewInternals->fy;
float z = 1;
rotate(y, z, -Reprojection->ax * PI / 180); // производим повороты
rotate(x, z, -Reprojection->ay * PI / 180);
rotate(x, y, -Reprojection->az * PI / 180);
mx.at<float>(j, i) = Reprojection->internals.fx*x/z+Reprojection->internals.cx;
my.at<float>(j, i) = Reprojection->internals.fy*y/z+Reprojection->internals.cy;
}
}
// функция opencv преобразования снимка с субпиксельной точностью
remap(*SrcImg, *DstImg, mx, my, CV_INTER_LINEAR, BORDER_CONSTANT, Scalar(0,0,0) );
mx.release();
my.release();
}
}
...
// исходные данные
REPROJECTION reproj[] =
{
{
{ 2117, 2328, 4589, 4589 }, // положение оптической оси 2117, 2328; фокусное - 4589
0, -12.52636814, 3.29980469 // углы поворота вокруг осей
},
{
{ 2117, 2368, 4623, 4623 }, // положение оптической оси 2117, 2368; фокусное - 4623
5.609776, 5.01366234, 1.30566382 // углы поворота вокруг осей
}
}; // положения оптических осей сдвинуты на одно и то же значение (4 по горизонтали, 2 по вертикали) относительно центрального креста для обоих снимков. впрочем, если не сдвигать, разница всё равно невелика, просто так чуть лучше
INTERNALS internals[DA_COUNT] =
{
{ sz.width/2-1000, sz.height/2, fx1, fy1 },
{ sz.width/2+300, sz.height/2, fx1, fy1 }
};
// вызов собственно репроекции
reproject(&img[DA_LEFT], &rimg[DA_LEFT], &reproj[DA_LEFT], &internals[DA_LEFT]);
reproject(&img[DA_RIGHT], &rimg[DA_RIGHT], &reproj[DA_RIGHT], &internals[DA_RIGHT]);