컴퓨터 생성 질감 된 벽 페인트


48

내 방의 벽에 페인트는 거의 프랙탈 같은 3 차원 텍스처가 있습니다.

이미지 A

이 도전에서 당신은 내 벽의 일부가 될 수있는 것처럼 보이는 임의의 이미지를 생성하는 프로그램을 작성합니다.

아래는 내 벽에 다른 반점의 10 개의 이미지를 수집했습니다. 모두 거의 같은 조명을 가지고 있으며 벽에서 1 피트 떨어진 곳에서 카메라로 찍은 것입니다. 테두리는 2048 x 2048 픽셀로 고르게 잘린 다음 512 x 512로 조정되었습니다. 위의 이미지는 이미지 A입니다.

이들은 축소판 일뿐입니다. 이미지를 클릭하면 전체 크기로 볼 수 있습니다!

A : B : C : D : E :이미지 A 이미지 B 이미지 C 이미지 D 이미지 E

F : G : H : I : J :이미지 F 이미지 G 이미지 H 이미지 I 이미지 J

당신의 임무는 임의의 시드로 1에서 2 16 사이의 양의 정수를 취하는 프로그램을 작성하는 것 입니다. 각 값마다 내 벽의 "11 번째 이미지"인 것처럼 보이는 독특한 이미지를 생성합니다. 내 10 개 이미지와 일부 이미지를보고있는 사람이 컴퓨터로 생성 된 컴퓨터를 알 수없는 경우 매우 잘 수행 한 것입니다!

시청자가 코드를 실행하지 않고도 이미지를 볼 수 있도록 생성 된 이미지 중 일부를 과시하십시오.

이미지의 조명이 강도 나 색상이 완전히 균일하지 않다는 것을 알고 있습니다. 미안하지만 더 나은 조명 장비없이 할 수있는 최선입니다. 이미지에는 가변 조명이 필요하지 않습니다 (가능한 경우). 질감이 더 중요합니다.

세부

  • 이미지 처리 도구 및 라이브러리를 사용할 수 있습니다.
  • 원하는 일반적인 방식 (명령 줄, stdin, 명백한 변수 등)으로 입력을 가져옵니다.
  • 출력 이미지는 일반적인 무손실 이미지 파일 형식이거나 창 / 바우 저로 표시 될 수 있습니다.
  • 프로그래밍 방식으로 내 10 이미지를 분석 할 수 있지만 코드를 실행하는 모든 사람이 액세스 할 수 있다고 가정하지는 않습니다.
  • 프로그래밍 방식으로 이미지를 생성해야합니다. 내 이미지 중 하나 또는 다른 스톡 이미지의 약간의 변형을 하드 코딩 할 수 없습니다. (어쨌든 사람들은 당신을 위해 투표를 할 것입니다.)
  • 내장 의사 난수 생성기를 사용할 수 있으며 기간이 2 16 이상 이라고 가정합니다 .

채점

이것은 가장 인기있는 답변이므로이기는 인기 콘테스트입니다.


PerlinNoise + 잘림 + 음영
Octopus

21
벽면 이미지를 만들 수 없으므로 만화가 있습니다 !
Sp3000

8
@ Sp3000 그게 어떻게 된 일 이냐. 내가 찾고 있었다면 아마 내 천장을 선택했을 것입니다 , 그것은 잘 작동 할 수 있습니다 ...
Calvin 's Hobbies

답변:


65

GLSL (+ JavaScript + WebGL)

여기에 이미지 설명을 입력하십시오

라이브 데모 | GitHub 리포지토리

사용하는 방법

새로운 임의 이미지를 위해 페이지를 다시로드하십시오. 특정 시드를 먹이려면 브라우저의 콘솔을 열고로 전화하십시오 drawScreen(seed). 콘솔은로드시 사용 된 시드를 표시해야합니다.

나는 이것을 많은 플랫폼에서 실제로 테스트하지 않았으므로 그것이 효과가 없다면 알려주십시오. 물론 브라우저는 WebGL을 지원해야합니다. 오류는 왼쪽의 열 또는 브라우저 콘솔에 표시됩니다 (오류 유형에 따라 다름).

새로운 : 이제 "이동 광원"체크 박스에 체크하여, 생활에 조금 벽을 가져올 수 있습니다.

이 마법은 무엇입니까?

GitHub 계정 주위에 떠 다니는 WebGL 상용구 코드가 있습니다.이 코드는 지금 사용하고 WebGL에서 2D 그래픽을 신속하게 프로토 타이핑하는 데 사용합니다. 약간의 셰이더 마술을 사용하면 약간 3D로 보이게 할 수 있으므로 멋진 효과를 얻는 가장 빠른 방법이라고 생각했습니다. 대부분의 설정은 그 상용구 코드에서 가져온 것이므로이 제출을위한 라이브러리 가이 게시물에 포함되지 않을 것이라고 생각합니다. 관심이 있다면 GitHub 의 main.js (및 해당 폴더의 다른 파일)를 살펴보십시오 .

JavaScript는 WebGL 컨텍스트를 설정하고 시드를 셰이더에 균일하게 저장 한 다음 전체 컨텍스트에 단일 쿼드를 렌더링하는 것입니다. 버텍스 셰이더는 단순한 패스 스루 셰이더이므로 조각 매직에서 모든 마법이 발생합니다. 이것이 제가 이것을 GLSL 제출이라고 부른 이유입니다.

코드의 가장 큰 부분은 실제로 GitHub에서 찾은 Simplex 노이즈를 생성하는 입니다. 그래서 아래 코드 목록에서도 생략합니다. 중요한 부분은 snoise(vec2 coords)텍스처 또는 배열 조회를 사용하지 않고 심플 렉스 노이즈를 반환 하는 함수 를 정의한다는 것 입니다. 전혀 시드되지 않으므로 다른 노이즈를 얻는 트릭은 시드를 사용하여 조회 위치를 결정하는 것입니다.

그래서 여기에 간다 :

#ifdef GL_ES
precision mediump float;
#endif
#extension GL_OES_standard_derivatives : enable

uniform float uSeed;
uniform vec2 uLightPos;

varying vec4 vColor;
varying vec4 vPos;

/* ... functions to define snoise(vec2 v) ... */

float tanh(float x)
{
    return (exp(x)-exp(-x))/(exp(x)+exp(-x));
}

void main() {
    float seed = uSeed * 1.61803398875;
    // Light position based on seed passed in from JavaScript.
    vec3 light = vec3(uLightPos, 2.5);
    float x = vPos.x;
    float y = vPos.y;

    // Add a handful of octaves of simplex noise
    float noise = 0.0;
    for ( int i=4; i>0; i-- )
    {
        float oct = pow(2.0,float(i));
        noise += snoise(vec2(mod(seed,13.0)+x*oct,mod(seed*seed,11.0)+y*oct))/oct*4.0;
    }
    // Level off the noise with tanh
    noise = tanh(noise*noise)*2.0;
    // Add two smaller octaves to the top for extra graininess
    noise += sqrt(abs(noise))*snoise(vec2(mod(seed,13.0)+x*32.0,mod(seed*seed,11.0)+y*32.0))/32.0*3.0;
    noise += sqrt(abs(noise))*snoise(vec2(mod(seed,13.0)+x*64.0,mod(seed*seed,11.0)+y*64.0))/64.0*3.0;

    // And now, the lighting
    float dhdx = dFdx(noise);
    float dhdy = dFdy(noise);
    vec3 N = normalize(vec3(-dhdx, -dhdy, 1.0)); // surface normal
    vec3 L = normalize(light - vec3(vPos.x, vPos.y, 0.0)); // direction towards light source
    vec3 V = vec3(0.0, 0.0, 1.0); // direction towards viewpoint (straight up)
    float Rs = dot(2.0*N*dot(N,L) - L, V); // reflection coefficient of specular light, this is actually the dot product of V and and the direction of reflected light
    float k = 1.0; // specular exponent

    vec4 specularColor = vec4(0.4*pow(Rs,k));
    vec4 diffuseColor = vec4(0.508/4.0, 0.457/4.0, 0.417/4.0, 1.0)*dot(N,L);
    vec4 ambientColor = vec4(0.414/3.0, 0.379/3.0, 0.344/3.0, 1.0);

    gl_FragColor = specularColor + diffuseColor + ambientColor;
    gl_FragColor.a = 1.0;
}

그게 다야. 내일 더 설명을 추가 할 수도 있지만 기본 아이디어는 다음과 같습니다.

  • 임의의 조명 위치를 선택하십시오.
  • 프랙탈 패턴을 생성하기 위해 몇 옥타브의 노이즈를 추가하십시오.
  • 바닥을 거칠게 유지하려면 소음을 제곱하십시오.
  • tanh상단을 수평으로 맞추기 위해 소음을 공급하십시오 .
  • 상단 레이어에서 텍스처를 조금 더 늘리려면 옥타브를 두 개 더 추가하십시오.
  • 결과 표면의 법선을 계산합니다.
  • 스페 큘러 및 디퓨즈 라이트로 표면에 간단한 Phong 쉐이딩을 실행합니다. 색상은 첫 번째 예제 이미지에서 선택한 임의의 색상을 기반으로 선택됩니다.

17
이것은 벽 자체보다 더 현실적이다 : o
Quentin

1
더 많은 "정맥"/ "뱀"/ "벌레"는이 그림을 "벽"에 더 적합하게 만듭니다. 그러나 여전히 멋지다.
Nova

33

매스 매 티카 스패 클링

아래 앱은 임의의 이미지에 반점을 적용합니다. "새 패치"를 클릭하면 작업 할 새로운 랜덤 이미지가 생성되고 현재 설정에 따라 효과가 적용됩니다. 효과는 유화, 가우시안 필터, 포스터 및 엠보싱입니다. 각 효과는 독립적으로 조정할 수 있습니다. 난수 생성기의 시드는 1에서 2 ^ 16 사이의 정수일 수 있습니다.

업데이트 : 가장자리를 부드럽게하는 가우시안 필터가 이제 마지막으로 적용된 이미지 효과입니다. 이 수정으로, 포스터 효과는 더 이상 필요하지 않아 제거되었다.

Manipulate[
 GaussianFilter[ImageEffect[ImageEffect[r, {"OilPainting", o}], {"Embossing", e, 1.8}], g],
 Button["new patch", (SeedRandom[seed] r = RandomImage[1, {400, 400}])], 
 {{o, 15, "oil painting"}, 1, 20, 1, ContinuousAction -> False, Appearance -> "Labeled"}, 
 {{e, 1.64, "embossing"}, 0, 5, ContinuousAction -> False, Appearance -> "Labeled"},
 {{g, 5, "Gaussian filter"}, 1, 12, 1, ContinuousAction -> False, Appearance -> "Labeled"},
 {{seed, 1}, 1, 2^16, 1, ContinuousAction -> False, Appearance -> "Labeled"}, 
 Initialization :> (SeedRandom[seed]; r = RandomImage[1, {400, 400}])]

최종 결과


설명

설명은 약간 다른 버전을 기반으로하며, 포스터 화가 GaussianFilter적용되어 초기에 적용되었습니다. 그러나 여전히 각 이미지 효과가 이미지를 변경하는 방법을 명확히하는 역할을합니다. 최종 결과는 가장자리가 더 선명한 페인트 텍스처입니다. 가우스 필터가 끝에 만 적용되면 위 그림과 같이 결과가 더 부드러워집니다.

이미지 효과를 한 번에 하나씩 살펴 보겠습니다.

시작 이미지를 생성하십시오.

 r = RandomImage[1, {200, 200}]

임의의 이미지


레나는 각 이미지 효과가 실제와 같은 그림을 어떻게 변화시키는 지 보여줄 것입니다.

Lena = ExampleData[{"TestImage", "Lena"}]

레나


Lena에 적용된 유화 효과.

ImageEffect[Lena, {"OilPainting", 8}]

레나 오일

랜덤 이미지에 유화 효과가 적용되었습니다. 효과가 강화되었습니다 (8 대신 16).

 r1 = ImageEffect[r, {"OilPainting", 16}]

기름


Lena에 적용된 가우시안 필터 효과 (Lena의 유화 효과 버전이 아님). 반경은 10 픽셀입니다. (최종 버전에서는이 항목의 맨 위에 GaussianFilter가 최종 효과로 적용됩니다.)

 GaussianFilter[Lena, 10]

레나 가우시안.


r1에 약간 온화한 가우스 필터 효과가 적용되었습니다. 반경은 5 픽셀입니다.

 r2 = GaussianFilter[r1, 5]

가우스


Lena에 적용된 강력한 포스터 효과. (앱의 최종 버전에서는 포스터 화를 제거했습니다. 그러나 분석의 예제는 포스터 화가 포함 된 이전 버전을 기반으로했기 때문에 분석에 그대로 둡니다.)

 ImageEffect[Lena, {"Posterization", 2}]

레나 포스터 화


r2에 적용된 포스터 효과.

r3 = ImageEffect[r2, {"Posterization", 4}]

포스터 화하다


엠보싱 레나

 ImageEffect[Lena, {"Embossing", 1.2, 1.8}]

레나 엠보싱


엠보싱 r3은 이미지 처리를 완료합니다. 이것은 OP의 천장과 비슷하게 보이기위한 것입니다.

 ceilingSample = ImageEffect[r3, {"Embossing", 1.2, 1.8}]

양각


궁금한 점은 동일한 이미지 효과가 적용된 Lena입니다.

lena4


... Lena 이미지를 얻을 수있는 내장 기능이 있습니까? LOL.
user253751

7
예. Mathematica에는 이미지 처리 테스트에 사용되는 약 30 개의 내장 사진이 있습니다.
DavidC

약간의 수정 RandomInteger만으로 시드를 공급할 수 있어 특정 출력을 보장 할 수 있습니다. 아니면 효과가 적용되는 비 랜덤 이미지의 시작과 같은 다른 것을 의미합니까?
DavidC

1
이제 1에서 2 ^ 16 사이의 시드를 허용합니다.
DavidC

1
Lena will show us how each image effect transforms a life-like picture나를 LOL로 만들었 기 때문에 +1 이상한 점은 최종 Lena 이미지가 Aztec 또는 Inca가 왼쪽을 향하고 머리 장식을 착용하고 나뭇 가지를 마치 마치 마치 마치 마치 것처럼 보이는 것처럼 보입니다.
레벨 리버 세인트

13

POV- 레이

많은 골프 잠재력, povray /RENDER wall.pov -h512 -w512 -K234543 여기에 이미지 설명을 입력하십시오

먼저 임의의 텍스처를 생성하지만, 중지하지 않고 텍스처를 3D- 높이 필드로 변환하여 카메라의 방사형 그림자를보다 사실적으로 만듭니다. 그리고 좋은 측정을 위해 작은 범프의 질감을 추가합니다.
임의의 씨앗을 하드 코딩에서 떨어져있는 유일한 방법은 사용하는 것입니다 clock이은으로 전달, 애니메이션에 대한 의미 변수를 -K{number}플래그

#default{ finish{ ambient 0.1 diffuse 0.9 }} 

camera {location y look_at 0 right x}
light_source {5*y color 1}

#declare R1 = seed (clock); // <= change this

#declare HF_Function  =
 function{
   pigment{
     crackle turbulence 0.6
     color_map{
       [0.00, color 0.01]
       [0.10, color 0.05]
       [0.30, color 0.20]
       [0.50, color 0.31]
       [0.70, color 0.28]
       [1.00, color 0.26]
     }// end color_map
    scale <0.25,0.005,0.25>*0.7 
    translate <500*rand(R1),0,500*rand(R1)>
   } // end pigment
 } // end function

height_field{
  function  512, 512
  { HF_Function(x,0,y).gray * .04 }
  smooth 
  texture { pigment{ color rgb<0.6,0.55,0.5>}
            normal { bumps 0.1 scale 0.005}
            finish { phong .1 phong_size 400}
          } // end of texture  
  translate< -0.5,0.0,-0.5>
}

이 골프를 전혀 할 필요가 없습니다. 좋은 결과! :)
Martin Ender
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.