Программирование приложений на android
Создана: 31 Октября 2011 Пон 13:25:33.
Раздел: "Компьютерный раздел"
Сообщений в теме: 223, просмотров: 35127
-
Предполагается использовать алгоритм Хафа для нахождения высоты забора, т.е. для нахождения верхней и нижней линии стенки коридора, а также для нахождения места посадки (кругов с крестами)
Входные параметры для алгоритма Хафа
1. входное изображение. Оно должно быть 8-битным, но будет трактоваться как двоичное изображение (т.е. все ненулевые значения пикселей будут восприниматься как равные единичные величины).
2. Количество возвращаемых линий
3. Следующие два параметра, rho и theta, устанавливают желательное разрешение для линий (т.е. разрешение плоскости накопителя). Параметр rho вычисляется в пикселях, а параметр theta – в радианах, поэтому плоскость накопителя можно рассматривать как двухмерную гистограмму с ячейками размерностью rho пикселей на theta радиан.
4. Значение параметра threshold определяет величину, которая должна быть достигнута на плоскости накопителя, чтобы сообщить о нахождении линии. Этот последний параметр на практике несколько мудрёный, при чем он не нормализуется, поэтому ожидается, что пользователь сам будет его масштабировать с ростом размерности входного изображения для алгоритма SHT. Этот параметр, в действительности, определяет количество точек (на входном изображении), которые должны поддерживать линию, чтобы линия была добавлена в возвращаемый список.
[внешняя ссылка] -
Пусть наше изображение состоит из пикселов двух типов - "фоновых" и "точек интереса". Допустим фоновые пикселы имеют белый цвет, а точки интереса - черный
Задача алгоритма Хафа состоит в нахождении прямых образованных точками интереса. Идея алгоритма состоит в нахождении прямых проходящих через "достаточное" количество точек интереса
Сканируем изображение сверху-вниз, слева-направо в поисках точек интереса, пикселов имеющих черный цвет
Если нашли "черный пиксел" то надо построить множество пар R, teta для прямых которые проходят через этот пиксел
Для примера имеем матрицу 7*7 пикселов. Для каждой точки интереса строим 20 прямых, с углами по отношению к оси x - 0.314, 0.628 и так далее с интервалом дискретизации по углу равным 0.314
Для каждой прямой ищем ортогональный к ней вектор из центра координат из уравнения
R = x*cos (teta) + y*sin (teta) , где x и y координаты точки интереса
Теперь собственно алгоритм заполнения аккумуляторной матрицы
Цикл по j от нуля до 2*PI с шагом dteta
teta = j*dteta
R = Xi*cos(dteta) + Yi*sin(dteta)
R1 = 0
k = 0
Пока |R1 - R| > dR/2
R1 = R1 +dR
k = k+1
Конец Пока
A[k][j] = A[k][j] + 1
Конец цикла по j
[внешняя ссылка]
[внешняя ссылка] -
Входными данными для преобразования Хафа служат монохромные изображения. Процесс получения геометрического описания пространства изображения заключается в прохождении следующих этапов:
а)Ввод растрового цветного изображения.
б)Преобразование в полутоновое изображение.
в)Сглаживающая фильтрация (для устранения шумов).
г)Операторы выделения краев.
д)Бинаризация.
[внешняя ссылка] -
Алгоритм обработки видео получаемого с вертолета
Получаем видео с вертолета. 30 картинок в секунду. Берем из него один кадр, он цветной. Преобразуем его в полутоновый формат в градациях серого цвета. Каждый пиксел кодируется одним байтом
Преобразуем линейный массив пикселов в двухмерный с размерами исследуемой картинки
Код:
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
Graphics g = image.getGraphics();
// Рисует javaImage в заданном месте image
g.drawImage(javaImage, 0, 0, null);
g.dispose();
int[] lineData = new int[width * height];
int[][] result = new int[height][width];
image.getRaster().getPixels(0, 0, width, height, lineData);
int k = 0;
for (int x=0; x < height; x++){
for (int y=0; y < width; y++){
result[x][y]=lineData[k];
k++; }}
//int crgb1 = image.getRGB(10, 10);
int crgb1 = lineData[100];
//String srgb = Integer.toString(crgb);
String srgb1 = Integer.toHexString(crgb1);
System.out.println("Gray: " + srgb1);
[внешняя ссылка] -
Выделение краев. Алгоритм Собеля
Ссылка на файл .doc
[внешняя ссылка]
В результате применения разностных операторов получается, как правило, изображение со средним значением пикселя близким к нулю
Оцифруем изображение. Пусть значение яркости может меняться от нуля до семи. Ноль соответствует белому цвету, семь - черному
Теперь мы хотим убрать из картинки все кроме границ. Посмотрим как изменится содержимое ячеек после применения преобразования Собеля
Идея состоит в том чтобы вычислить разность между значениями яркости в соседних ячейках
В алгоритме Собеля используется восемь значений яркости пикселов о окрестностях центральной точки
Вот такая картинка получилась
-
Алгоритм полета
1. Взлет и движение в коридоре1. Определяем и контролируем во время движения расстояние до боковой стенки коридора и высоту полета робота. Для этого используем горизонтальную камеру и компас
2. Пролетаем через боковой проем в коридор2
3. Определяем расстояние до препятствия и положение проема в препятствии. Перемещаем робота прямо напротив проема и начинаем движение к препятствию
4. На расстоянии нескольких метров от препятствия снова позиционируем робота посередине проема и продолжаем движение с контролем расстояния от боковой стенки коридора
5. После преодоления препятствия ищем с помощью горизонтальной камеры место посадки. Позиционируем робота посередине места посадки, определяем расстояние до него и его положение на карте
6. Подлет к месту промежуточной посадки. На расстоянии нескольких метров от него снова позиционируем робота посередине места посадки. Посадку выполняем с помощью нижней камеры
7. Взлет и движение по камере
8. Посадка -
Пусть имеется полутоновое изображение пылесоса, в градациях серого цвета, с размерами 640*360
То есть цветную картинку переданную роботом преобразовали в полутоновую.
Видно что на картинке имеются искажения. Слева от пылесоса угол стенки кривой, а справа - линейка
Надо во-первых масштабировать картинку, т.е. уменьшить количество пикселов в изображении в четыре раза с помощью метода SCALE_SMOOTH объекта Image, а во-вторых обрезать полученное изображение с размерами 320*180 слева и справа на 140 пикселов. В результате должны получить картинку 40*180
1. Создаем экземпляр объекта BufferedImage с размерами 40*180
2. Исходную картинку масштабируем
3. Обрезаем слева и справа на 140 пикселов
Вот код для выполнения этих операций
Код:
BufferedImage image4 = new BufferedImage(40, 180, BufferedImage.TYPE_BYTE_GRAY);
fileName = "erbol7.bmp";
Image im2 = image.getScaledInstance(320, 180, Image.SCALE_SMOOTH);
image4.getGraphics().drawImage(im2, -140 , 0, null);
ImageIO.write(image4, "bmp", new File(outdir, fileName));
Получаем рисунок 40*180
Видна средняя часть пылесоса -
-
Боевой, телеуправляемый армейский робот России.
[внешняя ссылка]
Надувные самолеты и ракеты, а теперь еще и роботы в 3-d графике -
-
Как я выделял границы предметов изображенных на картинке с помощью преобразования Собеля
Сначала попробовал это проделать на матрице пикселов которую сам создал для теста. Потом когда получилось сделал это на реальном изображении которое получил от робота
Вот собственно матрица которую я использовал для теста программы реализующей преобразование Собеля
Код:
int[][] d = new int[][]{
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
Размерность матрицы 10 строк, 16 столбцов
А это код, который я использовал для выполнения преобразования
Код:
BufferedImage img1 = new BufferedImage(14, 8, BufferedImage.TYPE_BYTE_GRAY);
int[][] d = new int[][]{
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
int[][] c = new int[8][14];
for (int m=1; m < 9; m++){
for (int n=1; n < 15; n++){
int gx = d[m-1][n-1] + 2*d[m][n-1] + d[m+1][n-1] - (d[m-1][n+1]+2*d[m][n+1]+d[m+1][n+1]);
int gy = d[m-1][n-1] + 2*d[m-1][n] + d[m-1][n+1] - (d[m+1][n-1]+2*d[m+1][n]+d[m+1][n+1]);
c[m-1][n-1] = (Math.abs(gx) + Math.abs(gy))/4;
}}
for(int y=0; y<8; y++){
for (int x=0; x<14; x++){
img1.setRGB(x,y,(c[y][x] == 0) ? 0xFFFFFF : 0x000000);
}
}
fileName = "erbol10.bmp";
ImageIO.write(img1, "bmp", new File(outdir, fileName));
В результате имеем вот такую картинку
После того как тест сработал применил этот алгоритм к реальной картинке полученной из видео передаваемой роботом
На картинке опять же видна средняя часть пылесоса
Для преобразования использовал вот такой код
Код:
BufferedImage image4 = new BufferedImage(40, 180, BufferedImage.TYPE_BYTE_GRAY);
Image im2 = image.getScaledInstance(320, 180, Image.SCALE_SMOOTH);
image4.getGraphics().drawImage(im2, -140 , 0, null);
int[] lineData1 = new int[40 * 180];
int[][] a = new int[180][40];
int[][] b = new int[178][38];
image4.getRaster().getPixels(0, 0, 40, 180, lineData1);
int k1 = 0;
for (int y1=0; y1 < 180; y1++){
for (int x1=0; x1 < 40; x1++){
a[y1][x1]=lineData1[k1];
k1++; }}
for (int x = 0; x < 180; x++) {
for (int y = 0; y < 40; y++) {
if (a[x][y] < 64) a[x][y]=0;
if (a[x][y]>63 & a[x][y] < 128) a[x][y]=96;
if (a[x][y]>127 & a[x][y] < 192) a[x][y]=160;
if (a[x][y]>191) a[x][y]=255;
}}
for (int m=1; m < 179; m++){
for (int n=1; n < 39; n++){
int gx = a[m-1][n-1] + 2*a[m][n-1] + a[m+1][n-1] - (a[m-1][n+1]+2*a[m][n+1]+a[m+1][n+1]);
int gy = a[m-1][n-1] + 2*a[m-1][n] + a[m-1][n+1] - (a[m+1][n-1]+2*a[m+1][n]+a[m+1][n+1]);
b[m-1][n-1] = 255-(Math.abs(gx) + Math.abs(gy))/4;
}}
BufferedImage image5 = new BufferedImage(38, 178, BufferedImage.TYPE_BYTE_GRAY);
for (int x = 0; x < 178; x++) {
for (int y = 0; y < 38; y++) {
int gray=b[x][y];
image5.setRGB(y, x, gray << 16 | gray << 8 | gray);
}}
fileName = "erbol8.bmp";
ImageIO.write(image5, "bmp", new File(outdir, fileName));
Получил вот такую картинку