|
Алгоритмика Об алгоритмах вообще; методы, обсуждения способов решения |
12.12.2011, 12:51
|
#1
|
Unity/C# кодер
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений (для 5,323 пользователей)
|
Карта высот из картинки
Подскажите, есть ли какие-то специальные алгоритмы построения карты высот по картинке?
Нужно для дальнейшего преобразования в карту нормалей.
|
(Offline)
|
|
12.12.2011, 13:50
|
#2
|
Мастер
Регистрация: 13.06.2011
Сообщений: 1,103
Написано 481 полезных сообщений (для 1,836 пользователей)
|
Ответ: Карта высот из картинки
Насчет специальных алгоритмов я не знаю, по моему карта высот она и в Африке карта высот и вся подготовка может быть выполнена в графическом редакторе. А вот по нормалям чутка есть.
for(int i=0;i<uppersize;i++){
for(int j=0;j<uppersize;j++){
int x0=i-1,x1=i+1,y0=j-1,y1=j+1;
//check of indexes size
if(i==0){x0=uppersize-1;}
if(i==uppersize-1){x1=0;}
if(j==0){y0=uppersize-1;}
if(j==uppersize-1){y1=0;}
//normals
float3 a00(-1,first->seed[x0][y0]-first->seed[i][j],-1); a00.normalize();
float3 a10(0,first->seed[i][y0]-first->seed[i][j],-1); a10.normalize();
float3 a20(1,first->seed[x1][y0]-first->seed[i][j],-1); a20.normalize();
float3 a01(-1,first->seed[x0][j]-first->seed[i][j],0); a01.normalize();
float3 a11(0,first->seed[i][j]-first->seed[i][j],0); a11.normalize();
float3 a21(1,first->seed[x1][j]-first->seed[i][j],0); a21.normalize();
float3 a02(-1,first->seed[x0][y1]-first->seed[i][j],1); a02.normalize();
float3 a12(0,first->seed[i][y1]-first->seed[i][j],1); a12.normalize();
float3 a22(1,first->seed[x1][y1]-first->seed[i][j],1); a22.normalize();
//result normal
float3 result=a00*a10+a10*a20+a20*a21+a21*a22+a22*a12+a12*a02+a02*a01+a01*a00;result.normalize();
norm[i][j]=-1*result;
}}
first->seed[x0][y1] - это моя карта высот там
Плюс даже из гладкой карты высот получится наждачная бумага вместо приличной карты нормалей, но она довольно легко сглаживается gausian blur'ом
int radius=32;
gauss_mask=new float*[radius];
for(int i=0;i<radius;i++){gauss_mask[i]=new float[radius];}
for(int i=0;i<radius;i++){
for(int j=0;j<radius;j++){
gauss_mask[i][j]=gaussian_blur(i,j, 12.4);
}}
float gaussian_blur(int x,int y, float sigma)
{
float koff=(1/sqrt(2*M_PI*pow(sigma,2)))*pow(M_E,-(x*x+y*y)/(2*sigma*sigma));
return koff;
}
и после построения маски и применения её к изначальной карте нормалей получался более приличный результат.
for(int i=0;i<uppersize;i++){
for(int j=0;j<uppersize;j++){
for(int x=0;x<radius;x++){
for(int y=0;y<radius;y++){
//now will sum all here
if(x==0 && y==0){normb[i][j]=gauss_mask[x][y]*norm[i][j];}
else if((x==0 && y!=0) ||(x!=0 && y==0)){
int x0=i-x,x1=i+x,y0=j-y,y1=j+y;
if(x0<0){x0=uppersize+x0;}
if(x1>=uppersize){x1=x1-uppersize;}
if(y0<0){y0=uppersize+y0;}
if(y1>=uppersize){y1=y1-uppersize;}
normb[i][j]=normb[i][j]+ 0.5*gauss_mask[x][y]*(norm[x0][y0]+norm[x1][y0]+norm[x0][y1]+norm[x1][y1]);
}
else{
int x0=i-x,x1=i+x,y0=j-y,y1=j+y;
if(x0<0){x0=uppersize+x0;}
if(x1>=uppersize){x1=x1-uppersize;}
if(y0<0){y0=uppersize+y0;}
if(y1>=uppersize){y1=y1-uppersize;}
normb[i][j]=normb[i][j]+gauss_mask[x][y]*(norm[x0][y0]+norm[x1][y0]+norm[x0][y1]+norm[x1][y1]);
}
}}
normb[i][j].normalize();
}}
|
(Offline)
|
|
12.12.2011, 13:55
|
#3
|
Unity/C# кодер
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений (для 5,323 пользователей)
|
Ответ: Карта высот из картинки
Нормали я считать умею, а вот карту высот по цветному изображению построить тяжело.
|
(Offline)
|
|
12.12.2011, 13:57
|
#4
|
Unity/C# кодер
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений (для 5,323 пользователей)
|
Ответ: Карта высот из картинки
Попробую использовать формулу grayscale
Lum := Red * 0.299 + Green * 0.587 + Blue * 0.114;
|
(Offline)
|
|
12.12.2011, 14:06
|
#5
|
Мастер
Регистрация: 13.06.2011
Сообщений: 1,103
Написано 481 полезных сообщений (для 1,836 пользователей)
|
Ответ: Карта высот из картинки
В смысле фотку со спутника к карте высот образовывающей похожий ландшафт привести?
|
(Offline)
|
|
12.12.2011, 14:18
|
#6
|
Unity/C# кодер
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений (для 5,323 пользователей)
|
Ответ: Карта высот из картинки
Ну похожий явно не получится, но ты понял задачу)
|
(Offline)
|
|
12.12.2011, 14:30
|
#7
|
Мастер
Регистрация: 13.06.2011
Сообщений: 1,103
Написано 481 полезных сообщений (для 1,836 пользователей)
|
Ответ: Карта высот из картинки
А почему нельзя топологическую карту очищенную от мусора использовать? Зря что ли геодезисты с теодолитами ноги по горам ломали? Тем паче, что там есть явная зависимость высоты от цвета, плюс линиями одинаковая высота показана.
|
(Offline)
|
|
12.12.2011, 14:52
|
#8
|
Терабайт исходников
Регистрация: 13.09.2008
Сообщений: 3,947
Написано 2,189 полезных сообщений (для 6,051 пользователей)
|
Ответ: Карта высот из картинки
если необязательно свой код, то CrazyBump умеет что-то подобное
|
(Offline)
|
|
12.12.2011, 15:02
|
#9
|
Unity/C# кодер
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений (для 5,323 пользователей)
|
Ответ: Карта высот из картинки
Сообщение от dsd
А почему нельзя топологическую карту очищенную от мусора использовать? Зря что ли геодезисты с теодолитами ноги по горам ломали? Тем паче, что там есть явная зависимость высоты от цвета, плюс линиями одинаковая высота показана.
|
не не, у меня не связано с ландшафтом)
Вопрос в экономии ресурсов в проекте. Если например можно не скачивать нормалмэпы с сервера а генерировать.
|
(Offline)
|
|
Сообщение было полезно следующим пользователям:
|
|
12.12.2011, 16:27
|
#10
|
Бывалый
Регистрация: 16.09.2011
Сообщений: 863
Написано 257 полезных сообщений (для 546 пользователей)
|
Ответ: Карта высот из картинки
(red+green+blue) /(255*3)
ne?
|
(Offline)
|
|
12.12.2011, 16:36
|
#11
|
Unity/C# кодер
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений (для 5,323 пользователей)
|
Ответ: Карта высот из картинки
не, grayscale дает лучший эффект в таком случае.
|
(Offline)
|
|
12.12.2011, 17:17
|
#12
|
Мастер
Регистрация: 13.06.2011
Сообщений: 1,103
Написано 481 полезных сообщений (для 1,836 пользователей)
|
Ответ: Карта высот из картинки
А если пытаться выделить на текстуре те участки, где цвет меняет оттенок по трем каналам одинаково. То получается, что текущий цвет в пятне/ максимальный цвет в пятне => cos(угол между нормаль текущей точки и нормаль само светлой в пятне(0,1,0)). Потом исходя из расстояния и угла вектора от точки до точки на изображении получать еще один вектор. Потом неведомым образом после разглядывания результата, бааац и нормалмапа?
|
(Offline)
|
|
Эти 2 пользователя(ей) сказали Спасибо dsd за это полезное сообщение:
|
|
12.12.2011, 17:19
|
#13
|
Unity/C# кодер
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений (для 5,323 пользователей)
|
Ответ: Карта высот из картинки
Если получится, то дай знать)))
Я пока остановился на grayscale.
|
(Offline)
|
|
20.12.2011, 23:46
|
#14
|
Мастер
Регистрация: 13.06.2011
Сообщений: 1,103
Написано 481 полезных сообщений (для 1,836 пользователей)
|
Ответ: Карта высот из картинки
В рендерманке есть один шейдер, который из
делает:
вершинный
struct VS_OUTPUT {
float4 Pos: POSITION;
float2 texCoord: TEXCOORD;
};
VS_OUTPUT main(float4 Pos: POSITION){
VS_OUTPUT Out;
// Clean up inaccuracies
Pos.xy = sign(Pos.xy);
Out.Pos = float4(Pos.xy, 0, 1);
// Image-space
Out.texCoord.x = 0.5 * (1 + Pos.x);
Out.texCoord.y = 0.5 * (1 - Pos.y);
return Out;
}
пиксельный
float TextureSize: register(c1);
float4 lightness: register(c0);
sampler BaseMap: register(s0);
// The Sobel filter extracts the first order derivates of the image,
// that is, the slope. The slope in X and Y directon allows us to
// given a heightmap evaluate the normal for each pixel. This is
// the same this as ATI's NormalMapGenerator application does,
// except this is in hardware.
//
// These are the filter kernels:
//
// SobelX SobelY
// 1 0 -1 1 2 1
// 2 0 -2 0 0 0
// 1 0 -1 -1 -2 -1
float4 main(float2 texCoord: TEXCOORD) : COLOR {
float off = 1.0 / TextureSize;
// Take all neighbor samples
float4 s00 = tex2D(BaseMap, texCoord + float2(-off, -off));
float4 s01 = tex2D(BaseMap, texCoord + float2( 0, -off));
float4 s02 = tex2D(BaseMap, texCoord + float2( off, -off));
float4 s10 = tex2D(BaseMap, texCoord + float2(-off, 0));
float4 s12 = tex2D(BaseMap, texCoord + float2( off, 0));
float4 s20 = tex2D(BaseMap, texCoord + float2(-off, off));
float4 s21 = tex2D(BaseMap, texCoord + float2( 0, off));
float4 s22 = tex2D(BaseMap, texCoord + float2( off, off));
// Slope in X direction
float4 sobelX = s00 + 2 * s10 + s20 - s02 - 2 * s12 - s22;
// Slope in Y direction
float4 sobelY = s00 + 2 * s01 + s02 - s20 - 2 * s21 - s22;
// Weight the slope in all channels, we use grayscale as height
float sx = dot(sobelX, lightness);
float sy = dot(sobelY, lightness);
// Compose the normal
float3 normal = normalize(float3(sx, sy, 1));
// Pack [-1, 1] into [0, 1]
return float4(normal * 0.5 + 0.5, 1);
}
NormalMapFilter называется
|
(Offline)
|
|
Сообщение было полезно следующим пользователям:
|
|
Ваши права в разделе
|
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 11:55.
|