Выровнять уже захваченные изображения rgb и глубины

Я пытаюсь привязать два изображения – одну rgb и другую глубину, используя MATLAB. Обратите внимание, что я проверил несколько мест для этого – как здесь , здесь, где требуется устройство kinect, и здесь, где указано, что параметры камеры необходимы для калибровки. Мне также предложили использовать EPIPOLAR GEOMETRY для соответствия двум изображениям, хотя я не знаю, как это сделать. Набор данных, на который я имею в виду, приведен в наборе данных rgb-dt . Один из таких примеров показан ниже:

образ

Основная истина, которая в основном означает ограничивающие прямоугольники, которые определяют интересующую область лица, уже предоставлена, и я использую их для обрезки только областей лица. Ниже приведен код Matlab:

I = imread('1.jpg'); I1 = imcrop(I,[218,198,158,122]); I2 = imcrop(I,[243,209,140,108]); figure, subplot(1,2,1),imshow(I1); subplot(1,2,2),imshow(I2); 

Ниже показаны два изображения обрезанных rgb и глубины: cropped_images


Есть ли способ, с помощью которого мы можем регистрировать / сопоставлять изображения. Я взял подсказку отсюда, где основной оператор sobel был использован как на изображениях rgb, так и на глубине для создания карты границ, а затем ключевые точки должны быть сгенерированы для целей сопоставления. Здесь создаются карты кромок для обоих изображений.

edge_map ,

Однако они настолько шумны, что я не думаю, что мы сможем выполнить сопоставление ключевых слов для этих изображений.

Может ли кто-нибудь предложить некоторые алгоритмы в Matlab сделать то же самое?

prolog

Этот ответ основан на моем предыдущем ответе:

  • Включает ли Kinect инфракрасный просмотр смещение с глубиной обзора Kinect

Я вручную обрезаю входное изображение, чтобы выделить отдельные цвета и изображения глубины (так как моя программа нуждается в их разнесении.Это может вызвать незначительное смещение на несколько пикселей.Кроме того, как у меня нет глубины (изображение глубины 8bit только из-за gradleаций RGB ) то точность точности, с которой я работаю, очень плохая:

глубина

Таким образом, мои результаты отрицательно сказываются на этом. В любом случае, вот что вам нужно сделать:

  1. определить FOV для обоих изображений

    Поэтому найдите некоторые измеримые функции, видимые на обоих изображениях. Чем больше размер, тем точнее результат. Например, я выбираю:

    FOV

  2. сформировать облако точек или сетку

    Я использую изображение глубины в качестве ссылки, поэтому мое облако точек находится в своем FOV . Поскольку у меня нет расстояний, но 8bit вместо этого я преобразовал это на некоторое расстояние путем умножения на константу. Поэтому я сканирую изображение всей глубины и для каждого пикселя, который я создаю в моем массиве точек. Затем преобразуйте координату пикселя деления в цветное изображение FOV и скопируйте его цвет. что-то вроде этого (в C ++ ):

     picture rgb,zed; // your input images struct pnt3d { float pos[3]; DWORD rgb; pnt3d(){}; pnt3d(pnt3d& a){ *this=a; }; ~pnt3d(){}; pnt3d* operator = (const pnt3d *a) { *this=*a; return this; }; /*pnt3d* operator = (const pnt3d &a) { ...copy... return this; };*/ }; pnt3d **xyz=NULL; int xs,ys,ofsx=0,ofsy=0; void copy_images() { int x,y,x0,y0; float xx,yy; pnt3d *p; for (y=0;ypos[0]=2.000*((float(x)/float(xs))-0.5); p->pos[1]=2.000*((float(y)/float(ys))-0.5)*(float(ys)/float(xs)); p->pos[2]=10.0*float(DWORD(zed.p[y][x].db[0]))/255.0; // convert dept image x,y to color image space (FOV correction) xx=float(x)-(0.5*float(xs)); yy=float(y)-(0.5*float(ys)); xx*=98.0/108.0; yy*=106.0/119.0; xx+=0.5*float(rgb.xs); yy+=0.5*float(rgb.ys); x0=xx; x0+=ofsx; y0=yy; y0+=ofsy; // copy color from rgb image if in range p->rgb=0x00000000; // black if ((x0>=0)&&(x0=0)&&(y0rgb=rgb2bgr(rgb.p[y0][x0].dd); // OpenGL has reverse RGBorder then my image } } с picture rgb,zed; // your input images struct pnt3d { float pos[3]; DWORD rgb; pnt3d(){}; pnt3d(pnt3d& a){ *this=a; }; ~pnt3d(){}; pnt3d* operator = (const pnt3d *a) { *this=*a; return this; }; /*pnt3d* operator = (const pnt3d &a) { ...copy... return this; };*/ }; pnt3d **xyz=NULL; int xs,ys,ofsx=0,ofsy=0; void copy_images() { int x,y,x0,y0; float xx,yy; pnt3d *p; for (y=0;ypos[0]=2.000*((float(x)/float(xs))-0.5); p->pos[1]=2.000*((float(y)/float(ys))-0.5)*(float(ys)/float(xs)); p->pos[2]=10.0*float(DWORD(zed.p[y][x].db[0]))/255.0; // convert dept image x,y to color image space (FOV correction) xx=float(x)-(0.5*float(xs)); yy=float(y)-(0.5*float(ys)); xx*=98.0/108.0; yy*=106.0/119.0; xx+=0.5*float(rgb.xs); yy+=0.5*float(rgb.ys); x0=xx; x0+=ofsx; y0=yy; y0+=ofsy; // copy color from rgb image if in range p->rgb=0x00000000; // black if ((x0>=0)&&(x0=0)&&(y0rgb=rgb2bgr(rgb.p[y0][x0].dd); // OpenGL has reverse RGBorder then my image } } с picture rgb,zed; // your input images struct pnt3d { float pos[3]; DWORD rgb; pnt3d(){}; pnt3d(pnt3d& a){ *this=a; }; ~pnt3d(){}; pnt3d* operator = (const pnt3d *a) { *this=*a; return this; }; /*pnt3d* operator = (const pnt3d &a) { ...copy... return this; };*/ }; pnt3d **xyz=NULL; int xs,ys,ofsx=0,ofsy=0; void copy_images() { int x,y,x0,y0; float xx,yy; pnt3d *p; for (y=0;ypos[0]=2.000*((float(x)/float(xs))-0.5); p->pos[1]=2.000*((float(y)/float(ys))-0.5)*(float(ys)/float(xs)); p->pos[2]=10.0*float(DWORD(zed.p[y][x].db[0]))/255.0; // convert dept image x,y to color image space (FOV correction) xx=float(x)-(0.5*float(xs)); yy=float(y)-(0.5*float(ys)); xx*=98.0/108.0; yy*=106.0/119.0; xx+=0.5*float(rgb.xs); yy+=0.5*float(rgb.ys); x0=xx; x0+=ofsx; y0=yy; y0+=ofsy; // copy color from rgb image if in range p->rgb=0x00000000; // black if ((x0>=0)&&(x0=0)&&(y0rgb=rgb2bgr(rgb.p[y0][x0].dd); // OpenGL has reverse RGBorder then my image } } с picture rgb,zed; // your input images struct pnt3d { float pos[3]; DWORD rgb; pnt3d(){}; pnt3d(pnt3d& a){ *this=a; }; ~pnt3d(){}; pnt3d* operator = (const pnt3d *a) { *this=*a; return this; }; /*pnt3d* operator = (const pnt3d &a) { ...copy... return this; };*/ }; pnt3d **xyz=NULL; int xs,ys,ofsx=0,ofsy=0; void copy_images() { int x,y,x0,y0; float xx,yy; pnt3d *p; for (y=0;ypos[0]=2.000*((float(x)/float(xs))-0.5); p->pos[1]=2.000*((float(y)/float(ys))-0.5)*(float(ys)/float(xs)); p->pos[2]=10.0*float(DWORD(zed.p[y][x].db[0]))/255.0; // convert dept image x,y to color image space (FOV correction) xx=float(x)-(0.5*float(xs)); yy=float(y)-(0.5*float(ys)); xx*=98.0/108.0; yy*=106.0/119.0; xx+=0.5*float(rgb.xs); yy+=0.5*float(rgb.ys); x0=xx; x0+=ofsx; y0=yy; y0+=ofsy; // copy color from rgb image if in range p->rgb=0x00000000; // black if ((x0>=0)&&(x0=0)&&(y0rgb=rgb2bgr(rgb.p[y0][x0].dd); // OpenGL has reverse RGBorder then my image } } с picture rgb,zed; // your input images struct pnt3d { float pos[3]; DWORD rgb; pnt3d(){}; pnt3d(pnt3d& a){ *this=a; }; ~pnt3d(){}; pnt3d* operator = (const pnt3d *a) { *this=*a; return this; }; /*pnt3d* operator = (const pnt3d &a) { ...copy... return this; };*/ }; pnt3d **xyz=NULL; int xs,ys,ofsx=0,ofsy=0; void copy_images() { int x,y,x0,y0; float xx,yy; pnt3d *p; for (y=0;ypos[0]=2.000*((float(x)/float(xs))-0.5); p->pos[1]=2.000*((float(y)/float(ys))-0.5)*(float(ys)/float(xs)); p->pos[2]=10.0*float(DWORD(zed.p[y][x].db[0]))/255.0; // convert dept image x,y to color image space (FOV correction) xx=float(x)-(0.5*float(xs)); yy=float(y)-(0.5*float(ys)); xx*=98.0/108.0; yy*=106.0/119.0; xx+=0.5*float(rgb.xs); yy+=0.5*float(rgb.ys); x0=xx; x0+=ofsx; y0=yy; y0+=ofsy; // copy color from rgb image if in range p->rgb=0x00000000; // black if ((x0>=0)&&(x0=0)&&(y0rgb=rgb2bgr(rgb.p[y0][x0].dd); // OpenGL has reverse RGBorder then my image } } 

    где **xyz – это точечное облако. 2D-массив выделяет разрешение изображения глубины. picture – мой class изображения для DIP, поэтому здесь некоторые соответствующие участники:

    • xs,ys – разрешение изображения в пикселях
    • p[ys][xs] – это прямой доступ к пикселю изображения как объединение DWORD dd; BYTE db[4]; DWORD dd; BYTE db[4]; поэтому я могу получить доступ к цвету в виде одиночной 32-битной переменной или каждого цветового канала отдельно.
    • rgb2bgr(DWORD col) просто переупорядочивает цветные каналы от RGB до BGR .
  3. сделать это

    Я использую OpenGL для этого, вот здесь код:

      glBegin(GL_QUADS); for (int y0=0,y1=1;y1z) z0=z; if (z1z) z0=z; if (z1z) z0=z; if (z1=3.90) continue; // 3.972 pre vsetko nad .=3.95ma 4.000 ak nechyti vobec nic if (z1-z0>=0.10) continue; glColor4ubv((BYTE* )&xyz[y0][x0].rgb); glVertex3fv((float*)&xyz[y0][x0].pos); glColor4ubv((BYTE* )&xyz[y0][x1].rgb); glVertex3fv((float*)&xyz[y0][x1].pos); glColor4ubv((BYTE* )&xyz[y1][x1].rgb); glVertex3fv((float*)&xyz[y1][x1].pos); glColor4ubv((BYTE* )&xyz[y1][x0].rgb); glVertex3fv((float*)&xyz[y1][x0].pos); } glEnd(); с  glBegin(GL_QUADS); for (int y0=0,y1=1;y1z) z0=z; if (z1z) z0=z; if (z1z) z0=z; if (z1=3.90) continue; // 3.972 pre vsetko nad .=3.95ma 4.000 ak nechyti vobec nic if (z1-z0>=0.10) continue; glColor4ubv((BYTE* )&xyz[y0][x0].rgb); glVertex3fv((float*)&xyz[y0][x0].pos); glColor4ubv((BYTE* )&xyz[y0][x1].rgb); glVertex3fv((float*)&xyz[y0][x1].pos); glColor4ubv((BYTE* )&xyz[y1][x1].rgb); glVertex3fv((float*)&xyz[y1][x1].pos); glColor4ubv((BYTE* )&xyz[y1][x0].rgb); glVertex3fv((float*)&xyz[y1][x0].pos); } glEnd(); с  glBegin(GL_QUADS); for (int y0=0,y1=1;y1z) z0=z; if (z1z) z0=z; if (z1z) z0=z; if (z1=3.90) continue; // 3.972 pre vsetko nad .=3.95ma 4.000 ak nechyti vobec nic if (z1-z0>=0.10) continue; glColor4ubv((BYTE* )&xyz[y0][x0].rgb); glVertex3fv((float*)&xyz[y0][x0].pos); glColor4ubv((BYTE* )&xyz[y0][x1].rgb); glVertex3fv((float*)&xyz[y0][x1].pos); glColor4ubv((BYTE* )&xyz[y1][x1].rgb); glVertex3fv((float*)&xyz[y1][x1].pos); glColor4ubv((BYTE* )&xyz[y1][x0].rgb); glVertex3fv((float*)&xyz[y1][x0].pos); } glEnd(); с  glBegin(GL_QUADS); for (int y0=0,y1=1;y1z) z0=z; if (z1z) z0=z; if (z1z) z0=z; if (z1=3.90) continue; // 3.972 pre vsetko nad .=3.95ma 4.000 ak nechyti vobec nic if (z1-z0>=0.10) continue; glColor4ubv((BYTE* )&xyz[y0][x0].rgb); glVertex3fv((float*)&xyz[y0][x0].pos); glColor4ubv((BYTE* )&xyz[y0][x1].rgb); glVertex3fv((float*)&xyz[y0][x1].pos); glColor4ubv((BYTE* )&xyz[y1][x1].rgb); glVertex3fv((float*)&xyz[y1][x1].pos); glColor4ubv((BYTE* )&xyz[y1][x0].rgb); glVertex3fv((float*)&xyz[y1][x0].pos); } glEnd(); с  glBegin(GL_QUADS); for (int y0=0,y1=1;y1z) z0=z; if (z1z) z0=z; if (z1z) z0=z; if (z1=3.90) continue; // 3.972 pre vsetko nad .=3.95ma 4.000 ak nechyti vobec nic if (z1-z0>=0.10) continue; glColor4ubv((BYTE* )&xyz[y0][x0].rgb); glVertex3fv((float*)&xyz[y0][x0].pos); glColor4ubv((BYTE* )&xyz[y0][x1].rgb); glVertex3fv((float*)&xyz[y0][x1].pos); glColor4ubv((BYTE* )&xyz[y1][x1].rgb); glVertex3fv((float*)&xyz[y1][x1].pos); glColor4ubv((BYTE* )&xyz[y1][x0].rgb); glVertex3fv((float*)&xyz[y1][x0].pos); } glEnd(); 

    Вам нужно добавить инициализацию OpenGL и настройки камеры и т. Д. Грубо. Здесь невысокий результат:

    цвета

  4. выровнять его

    Если вы заметили, я добавил ofsx,ofsy переменных для copy_images() . Это смещение между камерами. Я меняю их на стрелки copy_images клавиш на 1 пиксель, а затем вызываю copy_images и copy_images результат. Таким образом, я вручную нашел смещение очень быстро:

    выравнивать

    Как видите, смещение равно +17 пикселям по оси x и +4 пикселям по оси y. Здесь вид сбоку, чтобы лучше видеть глубины:

    боковая сторона

Надеюсь, это поможет

Ну, я пробовал это делать, прочитав много блогов и всех. Я все еще не уверен, что я делаю это правильно или нет. Пожалуйста, не стесняйтесь давать комментарии, если что-то найдено не так. Для этого я использовал представление mathworks fex, которое можно найти здесь: функция ginputc .

Код matlab выглядит следующим образом:

 clc; clear all; close all; % no of keypoint N = 7; I = imread('2.jpg'); I = rgb2gray(I); [Gx, Gy] = imgradientxy(I, 'Sobel'); [Gmag, ~] = imgradient(Gx, Gy); figure, imshow(Gmag, [ ]), title('Gradient magnitude') I = Gmag; [x,y] = ginputc(N, 'Color' , 'r'); matchedpoint1 = [xy]; J = imread('2.png'); [Gx, Gy] = imgradientxy(J, 'Sobel'); [Gmag, ~] = imgradient(Gx, Gy); figure, imshow(Gmag, [ ]), title('Gradient magnitude') J = Gmag; [x, y] = ginputc(N, 'Color' , 'r'); matchedpoint2 = [xy]; [tform,inlierPtsDistorted,inlierPtsOriginal] = estimateGeometricTransform(matchedpoint2,matchedpoint1,'similarity'); figure; showMatchedFeatures(J,I,inlierPtsOriginal,inlierPtsDistorted); title('Matched inlier points'); I = imread('2.jpg'); J = imread('2.png'); I = rgb2gray(I); outputView = imref2d(size(I)); Ir = imwarp(J,tform,'OutputView',outputView); figure; imshow(Ir, []); title('Recovered image'); figure,imshowpair(I,J,'diff'),title('Difference with original'); figure,imshowpair(I,Ir,'diff'),title('Difference with restored'); 

Шаг 1

Я использовал детектор кроссовок sobel для извлечения краев как для изображений глубины, так и для rgb, а затем использовал значения пороговых значений для получения краевой карты. В первую очередь я буду работать только с gradleиентной величиной. Это дает мне два изображения:

rgb_edge depth_edge

Шаг 2

Затем я использую ginput или ginputc для обозначения ключевых точек на обоих изображениях. Переписка между пунктами устанавливается мной заранее. Я пробовал использовать функции SURF но они плохо работают на изображениях глубины.

введите описание изображения здесь

Шаг 3

Используйте tform estimategeometrictransform чтобы получить матрицу преобразования tform а затем используйте эту матрицу для восстановления исходного положения перемещенного изображения. Следующий набор изображений рассказывает об этой истории.

Изображение matched_inlier

Восстановленное изображение

разница с оригиналом

разница с восстановленным

Конечно, я по-прежнему считаю, что результаты могут быть улучшены, если выбор ключевых точек на любом из изображений более разумно сделан. Я также думаю, что метод @Specktre лучше. Я только заметил, что в своем ответе я использовал отдельную пару изображений по сравнению с вопросом. Оба изображения поступают из одного набора данных, который можно найти здесь : dataset vap rgb-dt .

  • что может привести к сбросу стоп-кадра (я использую «throw», а не «throw ex»)
  • Какая лучшая библиотека обработки изображений java?
  • Как зарегистрировать ошибку Python с информацией об отладке?
  • Asp.net mvc override OnException в базовом controllerе продолжает распространяться в Application_Error
  • Сегментация изображения с использованием Mean Shift
  • 400 BAD запрос Значение кода ошибки HTTP?
  • Радиус многоканального изображения в RGB
  • Что я должен знать о Structured Exceptions (SEH) в C ++?
  • Алгоритм обнаружения наличия текста на изображении
  • Показывать номер строки в обработке исключений
  • Пакетный файл. Удалить все файлы и папки в каталоге
  • Interesting Posts

    Преобразование из строки научной нотации в float в C #

    Как рассчитать расстояние между двумя точками, используя их долготу и значение широты

    Как создать последовательный индекс на основе переменной группировки в фрейме данных

    Загрузка нескольких файлов с параметрами wget и обработки

    Передача аргументов по значению или по ссылке в объекте C

    Откройте изображение с помощью URI в средстве просмотра изображений галереи по умолчанию в Android

    Как запустить скрипт powershell как администратора

    Какую команду я могу использовать для рекурсивного переименования или перемещения файла в Windows?

    Создать JPA EntityManager без файла конфигурации persistence.xml

    Bash в Windows 10 – Каталоги, не появляющиеся при создании в Проводнике файлов

    Запуск файла bat при запуске в качестве администратора в Windows 7

    Производительность Cellfun и Simple Matlab Loop

    mongoDB / mongoose: уникальный, если не null

    Как сделать Quick Look предварительным просмотром текстовых файлов в UTF-8 по умолчанию?

    Можно использовать тип Nullable как общий параметр?

    Давайте будем гением компьютера.