[关闭]
@darkproject 2020-02-13T11:30:12.000000Z 字数 5107 阅读 877

TA测试题记录

记录


5道选2道做,自身美术实力的确还需要加强。有道比较不错的程序化建模题(待补中,打算用houdini和引擎内各实现一遍)。花了1天时间学习了py语法和pil库(查资料累死咯)据说第三问可以直接用pil库做,不过没有找到相关api,自身结合竞赛图论知识勉强怼了出来。


仅使用Pil库进行图片处理,r通道高斯模糊设置模糊半径,g通道边缘检测并设置阈值0.5,b通道根据g通道计算闭合区域,并对闭合区域咦其中心y值(纹理坐标系)填色。

  1. import os
  2. from PIL import Image
  3. from PIL import ImageFilter
  4. dx=[-1,0,0,1]
  5. dy=[0,-1,1,0]
  6. xmin,ymin,xmax,ymax=[],[],[],[]
  7. #思路:用PIL内置filter进行高斯模糊解决第一问
  8. #用PIL内置filter进行边缘检测,遍历图片对每个纹素进行阈值判断解决第二问
  9. #第三问:在边缘检测后的二值化图像求取闭合区域,通过深度优先搜索遍历黑色区域(非边缘部分)
  10. #对每个连通分量进行标记,然后记录xmin,xmax,ymin,ymax得到连通块的bbox求取中心坐标
  11. #栈模拟dfs防止溢出得不到结果,因为离线操作不太考虑时间效率。
  12. class node:
  13. def __init__(self,x,y):
  14. self.x=x
  15. self.y=y
  16. class Stack:
  17. def __init__(self):
  18. self.items = []
  19. def isEmpty(self):
  20. return self.items == []
  21. def push(self, item):
  22. self.items.append(item)
  23. def pop(self):
  24. return self.items.pop()
  25. def peek(self):
  26. return self.items[len(self.items)-1]
  27. def size(self):
  28. return len(self.items)
  29. def clear(self):
  30. self.items = []
  31. #栈模拟dfs
  32. def dfs(x,y,label,img):
  33. while(s.size()>0):
  34. cur=s.peek()
  35. flag[cur.x][cur.y]=label
  36. xmin[label-1]=min(xmin[label-1],cur.x)
  37. ymin[label-1]=min(ymin[label-1],cur.y)
  38. xmax[label-1]=max(xmax[label-1],cur.x)
  39. ymax[label-1]=max(ymax[label-1],cur.y)
  40. s.pop()
  41. for i in range(4):
  42. next=node(cur.x+dx[i],cur.y+dy[i])
  43. if(next.x<0 or next.y <0 or next.x>=width or next.y >=height): continue
  44. if(img.getpixel((next.x,next.y))==0 and flag[next.x][next.y]==0 ):
  45. s.push(next)
  46. def threshold(t,img):
  47. for w in range(0,width):
  48. for h in range(0,height):
  49. pixel=float(img.getpixel((w,h)))/255
  50. if (pixel>t):
  51. img.putpixel((w,h),255)
  52. else:
  53. img.putpixel((w,h),0)
  54. #记录相应的连通块及对应的bbox
  55. def connected(img):
  56. set=1
  57. xmin.append(width)
  58. ymin.append(height)
  59. xmax.append(0)
  60. ymax.append(0)
  61. for w in range(0,width):
  62. for h in range(0,height):
  63. if(img.getpixel((w,h))==0 and flag[w][h]==0):
  64. s.push(node(w,h))
  65. xmin.append(width)
  66. ymin.append(height)
  67. xmax.append(0)
  68. ymax.append(0)
  69. dfs(w,h,set,img)
  70. set+=1
  71. #按bbox得到的中心坐标y值对其连通块填充颜色
  72. def fill(img):
  73. for w in range(0,width):
  74. for h in range(0,height):
  75. if(flag[w][h]>0):
  76. num=flag[w][h]-1
  77. cy=ymin[num]+(ymax[num]-ymin[num])/2
  78. cy=cy/height
  79. cy=int(cy*255)
  80. img.putpixel((w,h),cy)
  81. if __name__ == '__main__':
  82. imgPath="D:/testD/F"
  83. newPath="D:/testD/F_n/"
  84. files=os.listdir(imgPath)
  85. for file in files:
  86. im=Image.open(imgPath+'/'+file)
  87. width=im.size[0]
  88. height=im.size[1]
  89. r,g,b,a=im.split()
  90. #第一问
  91. r=r.filter(ImageFilter.GaussianBlur(radius=3))
  92. g=g.filter(ImageFilter.FIND_EDGES)
  93. flag=[[0 for j in range(height)] for i in range(width)]
  94. s=Stack()
  95. #第二问
  96. threshold(0.5,g)
  97. b=g.copy()
  98. #第三问
  99. connected(b)
  100. fill(b)
  101. img=Image.merge("RGBA",[r,g,b,a])
  102. img.save(newPath+'/'+file,'png')

给定人物模型制作运动动画并进行物理渲染的线框效果展示。
制作思路:https://www.bilibili.com/read/cv3168157
TIM图片20191025140102.png-64kB

  1. Shader "TestC/wireframe"
  2. {
  3. Properties
  4. {
  5. [Toggle] _NoTriangle("NoTriangle",float)=0
  6. _wireThickness("wire thickness",Range(0,5))=0.05
  7. _wireColor("wire color",Color)=(1,1,1,1)
  8. _wireSmoothing("wire smoothing",Range(0,5))=1
  9. }
  10. SubShader
  11. {
  12. CGINCLUDE
  13. #include "UnityCG.cginc"
  14. #include "Lighting.cginc"
  15. fixed4 _wireColor;
  16. half _wireThickness;
  17. half _wireSmoothing;
  18. struct a2v{
  19. float4 vertex:POSITION;
  20. };
  21. struct v2g
  22. {
  23. float3 vpos:TEXCOORD0;
  24. float4 wpos : SV_POSITION;
  25. };
  26. struct g2f
  27. {
  28. float3 vpos:TEXCOORD1;
  29. float4 pos : SV_POSITION;
  30. float3 barycentric:TEXCOORD0;
  31. float3 worldNormal:TEXCOORD2;
  32. };
  33. v2g vert (a2v v)
  34. {
  35. v2g o;
  36. o.vpos=v.vertex.xyz;
  37. o.wpos = mul(unity_ObjectToWorld,v.vertex);
  38. return o;
  39. }
  40. float3 getNormal(float3 pos0, float3 pos1,float3 pos2)
  41. {
  42. float3 a=pos1-pos0;
  43. float b=pos2-pos0;
  44. return normalize(cross(a,b));
  45. }
  46. [maxvertexcount(3)]
  47. void geom(triangle v2g p[3],inout TriangleStream<g2f> stream)
  48. {
  49. g2f o1,o2,o3;
  50. float3 param=float3(0,0,0);
  51. #if _NOTRIANGLE_ON
  52. float EdgeA = length(p[0].vpos - p[1].vpos);
  53. float EdgeB = length(p[1].vpos - p[2].vpos);
  54. float EdgeC = length(p[2].vpos - p[0].vpos);
  55. if(EdgeA > EdgeB && EdgeA > EdgeC)
  56. param.y = 1.;
  57. else if (EdgeB > EdgeC && EdgeB > EdgeA)
  58. param.x = 1.;
  59. else
  60. param.z = 1.;
  61. #endif
  62. o1.pos=mul(UNITY_MATRIX_VP,p[0].wpos);
  63. o2.pos=mul(UNITY_MATRIX_VP,p[1].wpos);
  64. o3.pos=mul(UNITY_MATRIX_VP,p[2].wpos);
  65. float3 triangleNomral=getNormal(p[0].wpos,p[1].wpos,p[2].wpos);
  66. o1.worldNormal=triangleNomral;
  67. o2.worldNormal=triangleNomral;
  68. o3.worldNormal=triangleNomral;
  69. o1.barycentric=float3(1,0,0)+param;
  70. o2.barycentric=float3(0,0,1)+param;
  71. o3.barycentric=float3(0,1,0)+param;
  72. o1.vpos=p[0].vpos;
  73. o2.vpos=p[1].vpos;
  74. o3.vpos=p[2].vpos;
  75. stream.Append(o1);
  76. stream.Append(o2);
  77. stream.Append(o3);
  78. stream.RestartStrip();
  79. }
  80. inline float aa1 (float threshold, float dist) {
  81. float delta = fwidth(dist) * _wireSmoothing;
  82. threshold=threshold*delta;
  83. return smoothstep(threshold-delta, threshold+delta, dist);
  84. }
  85. fixed4 fragfront (g2f i) : SV_Target
  86. {
  87. i.worldNormal=normalize(i.worldNormal);
  88. fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.xyz;
  89. fixed3 worldlight_dir=normalize(_WorldSpaceLightPos0.xyz);
  90. fixed3 diffuse=_LightColor0.rgb*_wireColor.rgb*saturate(dot(normalize(i.worldNormal),worldlight_dir));
  91. float3 barycentric=float3(i.barycentric.x,i.barycentric.y,i.barycentric.z);
  92. float thickness=_wireThickness;
  93. float d=min(barycentric.x,min(barycentric.y,barycentric.z));
  94. float t=1-aa1(thickness,d);
  95. return fixed4(ambient+diffuse,t);
  96. }
  97. ENDCG
  98. Pass
  99. {
  100. Tags{"Queue"="AlphaTest" "LightMode"="ForwardBase"}
  101. Cull front
  102. AlphaToMask On
  103. CGPROGRAM
  104. #pragma shader_feature _NOTRIANGLE_ON
  105. #pragma vertex vert
  106. #pragma fragment fragfront
  107. #pragma geometry geom
  108. #pragma target 4.0
  109. ENDCG
  110. }
  111. Pass
  112. {
  113. Tags{"Queue"="AlphaTest" "LightMode"="ForwardBase"}
  114. Cull back
  115. AlphaToMask On
  116. CGPROGRAM
  117. #pragma shader_feature _NOTRIANGLE_ON
  118. #pragma vertex vert
  119. #pragma fragment fragfront
  120. #pragma geometry geom
  121. #pragma target 4.0
  122. ENDCG
  123. }
  124. }
  125. FallBack "Diffuse"
  126. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注