|
Масштабирование матрицы | ☑ | ||
---|---|---|---|---|
0
queit
14.11.11
✎
12:06
|
Всем привет.
Суть задачки следующая: есть большое изображение, из которого я плучаю часть (прямоугольную область). В этой области имеется изображение цифры. Далее я пределяю контуры цифры и загоняю это все дело в двумерный массив. Тем самым плучается некоторый отпечаток цифры. При этом размерность двумерного массива будет варьироваться в зависимисти от первоначальных размеров облассти (например, 9х19 - ширина и высота соответственно). Для примера, двумерный массив изображения цифры 1: 000011000 001111100 111111100 001111000 001111000 001111000 001111000 001111000 001111000 001111000 001111000 001111000 001111000 001111000 001111000 001111000 001111000 001111100 111111111 Далее есть дикое желание :-) загнать этот массив в массив 16х16, но таким образом, чтобы не потерялись данные. Нашел в иинете небольшой пссевдокод и перевел его на с++: int nSymbol; // кол-во значимых пикселей double percent; // процент заполнения Percent Points XY[17]; // массив относительных координат анализируемых ячеек int newH, newW; // новые высота и ширина int ki, kj; // вспомогательные координаты при масштабировании int Mas16x16[16][16]; // массив масштабированного изображения fill(Mas16x16[0], Mas16x16[0] + 16*16, 0); //---------------------------------------------------------------------------- // получаем процент заполнения как отношение кол-ва значимых пикселей к общему // кол-ву пикселей в границах образа // Percent будет необходим при анализе каждой ячейки в разбитом на 16х16 образе nSymbol = 0; for(int j = 0; j < cur_H; j++) for(int i = last_x; i < cur_x; i++) if(ArreyPix[j][i] == 1) nSymbol++; percent = (double) nSymbol / (cur_H*(cur_x - last_x)); percent = 0.99*percent; // коэф-т влияет на формирование матрицы 16х16 // > 1 - учитывается меньше значимых пикселей // < 1 - учитывается больше значимых пикселей //---------------------------------------------------------------------------- // разбиваем прямоугольник образа на 16 равных частей путем деления сторон на 2 // и получаем относительные координаты каждой ячейки newW = cur_x - last_x; XY[0].x = 0; XY[16].x = newW; XY[8].x = Divides(XY[16].x); XY[4].x = Divides(XY[8].x); XY[2].x = Divides(XY[4].x); XY[1].x = Divides(XY[2].x); XY[3].x = Divides((XY[4].x + XY[2].x)); XY[6].x = Divides((XY[8].x + XY[4].x)); XY[5].x = Divides((XY[6].x + XY[4].x)); XY[7].x = Divides((XY[8].x + XY[6].x)); XY[12].x = Divides((XY[16].x + XY[8].x)); XY[10].x = Divides((XY[12].x + XY[8].x)); XY[14].x = Divides((XY[16].x + XY[12].x)); XY[9].x = Divides((XY[10].x + XY[8].x)); XY[11].x = Divides((XY[12].x + XY[10].x)); XY[13].x = Divides((XY[14].x + XY[12].x)); XY[15].x = Divides((XY[16].x + XY[14].x)); newH = cur_H; XY[0].y = 0; XY[16].y = newH; XY[8].y = Divides(XY[16].y); XY[4].y = Divides(XY[8].y); XY[2].y = Divides(XY[4].y); XY[1].y = Divides(XY[2].y); XY[3].y = Divides((XY[4].y + XY[2].y)); XY[6].y = Divides((XY[8].y + XY[4].y)); XY[5].y = Divides((XY[6].y + XY[4].y)); XY[7].y = Divides((XY[8].y + XY[6].y)); XY[12].y = Divides((XY[16].y + XY[8].y)); XY[10].y = Divides((XY[12].y + XY[8].y)); XY[14].y = Divides((XY[16].y + XY[12].y)); XY[9].y = Divides((XY[10].y + XY[8].y)); XY[11].y = Divides((XY[12].y + XY[10].y)); XY[13].y = Divides((XY[14].y + XY[12].y)); XY[15].y = Divides((XY[16].y + XY[14].y)); //---------------------------------------------------------------------------- // анализируем каждую полученную ячейку в разбитом прямоугольнике образа // и создаем приведенную матрицу 16x16 for(kj = 0; kj < 15; kj++) for(ki = 0; ki < 15; ki++){ nSymbol = 0; for(int j = XY[kj].y; j < XY[kj+1].y; j++) // пробегаемся по ячейкам уже for(int i = last_x + XY[ki].x; i < last_x + XY[ki+1].x; i++) // в абсолютных координатах if(ArreyPix[j][i] == 1) nSymbol++; // считаем кол-во значимых пикселей (=1 -> черный цвет) // если отношение кол-ва знач. пикселей к общему кол-ву в ящейке > характерного процента заполнения то = 1 иначе = 0 if(nSymbol / max(1, ((XY[ki+1].x - XY[ki].x) * (XY[kj+1].y - XY[kj].y))) > percent) Mas16x16[kj][ki] = 1; else Mas16x16[kj][ki] = 0; // результат - приведенная матрица 16х16 } В результате пполучается: 000000000101000 000001010101010 010101010101010 000001010101000 000001010101000 000001010101000 000001010101000 000001010101000 000001010101000 000001010101000 000001010101000 000001010101000 000001010101000 000001010101000 000001010101000 Т.е. есть разрывы и неточности в результате. Подскажите, как сделать чтобы алгоритм сработал правильно (возможно где-то я ошибся)? Или возможно уже есть какое-то решение? |
|||
1
Axel2009
15.11.11
✎
11:16
|
матрица получается 15/15 судя по ноликам.
плюс ко всему по моему проще и лучше сначала в зависимости от масштаба увеличить до нужных размеров там где меньше. а после увеличения - уменьшать там где больше. |
|||
2
dk
15.11.11
✎
11:20
|
вроде стандартная задачка на масштабирование изображения, только вместо точки цифра
поищи работу с изображением - там несколько формул для 2д / 3д обработки изображений - масштабирование / поворот / зеркалирование / ... давно в институте проходили, но помню, что формулы были простые |
|||
3
queit
15.11.11
✎
14:27
|
(1) благодарю, верно подмечено.
должно быть так: for(kj = 0; kj <= 15; kj++) for(ki = 0; ki <= 15; ki++){ nSymbol = 0; for(int j = XY[kj].y; j < XY[kj+1].y; j++) // пробегаемся по ячейкам уже for(int i = last_x + XY[ki].x; i < last_x + XY[ki+1].x; i++) // в абсолютных координатах if(ArreyPix[j][i] == 1) nSymbol++; // считаем кол-во значимых пикселей (=1 -> черный цвет) // если отношение кол-ва знач. пикселей к общему кол-ву в ящейке > характерного процента заполнения то = 1 иначе = 0 if((double)nSymbol / max(1, ((XY[ki+1].x - XY[ki].x) * (XY[kj+1].y - XY[kj].y))) > percent) Mas16x16[kj][ki] = 1; else Mas16x16[kj][ki] = 0; // результат - приведенная матрица 16х16 } Результат полуается: 0000000001010000 0000010101010100 0101010101010100 0000010101010000 0000010101010000 0000010101010000 0000010101010000 0000010101010000 0000010101010000 0000010101010000 0000010101010000 0000010101010000 0000010101010000 0000010101010000 0000010101010000 0101010101010111 |
|||
4
queit
15.11.11
✎
14:27
|
но все равно есть пропуски
|
|||
5
queit
15.11.11
✎
14:30
|
(2) да, есть Аффинное преобразование
вот только там есть некий коэффициент масштабирования по осям ах и ау если взять реальную задачку, то коэффициенты получаются дробными, а у меня один элемент матрицы - это один пиксель, аа он неделимый. Получается, что нужно как-то рассматривать соседние элементы. что-то я совсем не соображу... :-( |
|||
6
acsent
15.11.11
✎
14:33
|
(5) Линейный масштабированием изменяешь размер?
|
|||
7
Axel2009
15.11.11
✎
14:37
|
(3) реально единичка правильная подставилась только в нижней строке праве 3 единички. в остальных всех случаях возвращается 0 между 1цами
|
|||
8
queit
15.11.11
✎
14:38
|
(6) не совсем понял что такое линейный, но попробую ответить.
о сути получаетя что да, т.к. у меня исходная матрица и масштабированная состоят из неделимых элементов |
|||
9
queit
15.11.11
✎
14:39
|
(7) получается, что просто увеличился масштаб путем добавления нулевых столбцов
|
|||
10
queit
15.11.11
✎
14:41
|
(6) какой еще можно взять масшаб?
|
|||
11
Axel2009
15.11.11
✎
14:42
|
(9) ну а нужно я так понимаю если между 2 соседние единички, тогда в результат вставлять единичку а не нолик
|
|||
12
queit
15.11.11
✎
14:45
|
(11) меня тоже первоначально такая идея посещала.
После него пребежаться по результитующей матрице и доставить единицы, по правилу: если левый и правый сосед единицы, то ставим единицу. только пока не знаю как быть с граничными элементами. Вот, напиример, цифра 2 выглядит так: 0000000101110000 0000011101111000 0001011101111100 0011011101111110 0011000000111110 0000000000011110 0000000000011100 0000000000011100 0000000000011000 0000000000110000 0000000001110000 0000000101100000 0000001100000011 0000011101111110 0001011101111110 0011011101111110 Справа в верху там не нужно сставить 1, хотя от того что я их туда поставлю суть не поменяется |
|||
13
acsent
15.11.11
✎
14:47
|
Тебе нужно просто изменить размер рисунка?
|
|||
14
acsent
15.11.11
✎
14:47
|
Для начала погугли какие алгоритмя изменения размера есть
|
|||
15
queit
15.11.11
✎
14:47
|
но меня вот все равно любопытство распирает - этот же код есть на delphi:
nSymbol := 0; for j := yTop to yBottom do for i := xLeft to xRight do if MasY[j][i] = 0 then inc(nSymbol); Percent := nSymbol / ((yBottom - yTop)*(xRight - xLeft)); Percent := 0.99*Percent; // коэф-т влияет на формирование матрицы 16х16 // > 1 - учитывается меньше значимых пикселей // < 1 - учитывается больше значимых пикселей //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // разбиваем прямоугольник образа на 16 равных частей путем деления сторон на 2 // и получаем относительные координаты каждой ячейки W := xRight - xLeft;; XY[0].x := 0; XY[16].x := W; XY[8].x := XY[16].x div 2; XY[4].x := XY[8].x div 2; XY[2].x := XY[4].x div 2; XY[1].x := XY[2].x div 2; XY[3].x := (XY[4].x + XY[2].x) div 2; XY[6].x := (XY[8].x + XY[4].x) div 2; XY[5].x := (XY[6].x + XY[4].x) div 2; XY[7].x := (XY[8].x + XY[6].x) div 2; XY[12].x := (XY[16].x + XY[8].x) div 2; XY[10].x := (XY[12].x + XY[8].x) div 2; XY[14].x := (XY[16].x + XY[12].x) div 2; XY[9].x := (XY[10].x + XY[8].x) div 2; XY[11].x := (XY[12].x + XY[10].x) div 2; XY[13].x := (XY[14].x + XY[12].x) div 2; XY[15].x := (XY[16].x + XY[14].x) div 2; H := yBottom - yTop; XY[0].y := 0; XY[16].y := H; XY[8].y := XY[16].y div 2; XY[4].y := XY[8].y div 2; XY[2].y := XY[4].y div 2; XY[1].y := XY[2].y div 2; XY[3].y := (XY[4].y + XY[2].y) div 2; XY[6].y := (XY[8].y + XY[4].y) div 2; XY[5].y := (XY[6].y + XY[4].y) div 2; XY[7].y := (XY[8].y + XY[6].y) div 2; XY[12].y := (XY[16].y + XY[8].y) div 2; XY[10].y := (XY[12].y + XY[8].y) div 2; XY[14].y := (XY[16].y + XY[12].y) div 2; XY[9].y := (XY[10].y + XY[8].y) div 2; XY[11].y := (XY[12].y + XY[10].y) div 2; XY[13].y := (XY[14].y + XY[12].y) div 2; XY[15].y := (XY[16].y + XY[14].y) div 2; //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // анализируем каждую полученную ячейку в разбитом прямоугольнике образа // и создаем приведенную матрицу 16x16 for kj := 0 to 15 do for ki := 0 to 15 do begin nSymbol := 0; for j := yTop + XY[kj].y to yTop + XY[kj+1].y do // пробегаемся по ячейкам уже for i := xLeft + XY[ki].x to xLeft + XY[ki+1].x do // в абсолютных координатах if MasY[j][i] = 0 then inc(nSymbol); // считаем кол-во значимых пикселей (=0 -> черный цвет) // если отношение кол-ва знач. пикселей к общему кол-ву в ящейке > характерного процента заполнения то = 1 иначе = 0 if nSymbol / MAX(1, ((XY[ki+1].x - XY[ki].x) * (XY[kj+1].y - XY[kj].y))) > Percent then Result[kj][ki] := 1 else Result[kj][ki] := 0; // результат - приведенная матрица 16х16 end; если ему подссовывать тоже самое изображение, то он все правильно делает, а вот на c++ ниига не хочет :-) тут либо я где-то ошибся либо нужно сделать какую-то доработку |
|||
16
Axel2009
15.11.11
✎
14:48
|
считаем кол-во значимых пикселей (=0 -> черный цвет)
|
|||
17
queit
15.11.11
✎
14:50
|
(14) конечно погуглил :-)
(13) по сути дела да, но я там если изменять изображения другими методами, то могут возникнуть градации серого в ненужных местах + нужно применять фильтры. в общем как-то сложно все |
|||
18
queit
15.11.11
✎
14:51
|
(16) там считается что значимый пиксель 0, а у меня 1 - суть от этого не меняется
|
|||
19
aleks-id
15.11.11
✎
14:51
|
SetStretchBltMode, StretchDIBits, StretchBlt
сначала колдуй с битмапом, потом заколдованый в 16х16 преобразуй в двоичные данные. |
|||
20
queit
15.11.11
✎
14:52
|
(19) ок, спасибо. ща попробую что там делается
|
|||
21
queit
15.11.11
✎
15:47
|
м-да, функции SetStretchBltMode, StretchDIBits, StretchBlt хороша вещь, но не совсем понятно, во-первых, как преобразовать bitmap в DC, а потом обратно, во-вторых, скорее всего произойдет искажение (судя по форумам) и придется применять какие-то фильтры.
Проще скорее всего разобраться что ни так в моём коде, но все равно покопаю указанные функции. |
|||
22
queit
15.11.11
✎
17:35
|
всё! разрешилась проблема :-)
вот такой код должен быть: for(int j = XY[kj].y; j < XY[kj+1].y; j++) for(int i = last_x + XY[ki].x; i <= last_x + XY[ki+1].x; i++) а то я уже пост обработку зафигачил: int last_value; for(kj = 0; kj <= 16; kj++) for(ki = 0; ki <= 16; ki++){ if((Mas16x16[kj][ki-1])&&(Mas16x16[kj][ki+1])) Mas16x16[kj][ki] = 1; } Благодарю всех откликнувшихся! ))) |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |