forked from spiraltechnica/Spout-for-Python
-
Notifications
You must be signed in to change notification settings - Fork 1
/
spout_NST_receiver.py
177 lines (137 loc) · 6.66 KB
/
spout_NST_receiver.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# Add relative directory ../Library to import path, so we can import the SpoutSDK.pyd library. Feel free to remove these if you put the SpoutSDK.pyd file in the same directory as the python scripts.
import sys
sys.path.append('../Library')
import tensorflow as tf
import numpy as np
import transform
import argparse
import time
import SpoutSDK
import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GL.framebufferobjects import *
from OpenGL.GLU import *
"""parsing and configuration"""
def parse_args():
desc = "Tensorflow implementation of 'Perceptual Losses for Real-Time Style Transfer and Super-Resolution', Spout receiver version"
parser = argparse.ArgumentParser(description=desc)
parser.add_argument('--style_model', type=str, default='style/Checkpoints/saraswati.ckpt', help='location for model file (*.ckpt)')
parser.add_argument('--spout_size', nargs = 2, type=int, default=[640, 480], help='Width and height of the spout receiver')
parser.add_argument('--spout_name', type=str, default='Composition - Resolume Arena', help='Spout receiving name - the name of the sender you want to receive')
parser.add_argument('--window_size', nargs = 2, type=int, default=[640, 480], help='Width and height of the window')
return parser.parse_args()
"""main"""
def main():
# parse arguments
args = parse_args()
# window details
width = args.window_size[0]
height = args.window_size[1]
display = (width,height)
# window setup
pygame.init()
pygame.display.set_caption('Spout Neural Style Receiver')
pygame.display.set_mode(display, DOUBLEBUF|OPENGL)
# OpenGL init
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(0,width,height,0,1,-1)
glMatrixMode(GL_MODELVIEW)
glDisable(GL_DEPTH_TEST)
glClearColor(0.0,0.0,0.0,0.0)
glEnable(GL_TEXTURE_2D)
# init spout receiver
receiverName = args.spout_name
spoutReceiverWidth = args.spout_size[0]
spoutReceiverHeight = args.spout_size[1]
# create spout receiver
spoutReceiver = SpoutSDK.SpoutReceiver()
# Its signature in c++ looks like this: bool pyCreateReceiver(const char* theName, unsigned int theWidth, unsigned int theHeight, bool bUseActive);
spoutReceiver.pyCreateReceiver(receiverName,spoutReceiverWidth,spoutReceiverHeight, False)
# create textures for spout receiver and spout sender
textureReceiveID = glGenTextures(1)
textureStyleID = glGenTextures(1)
# initalise receiver texture
glBindTexture(GL_TEXTURE_2D, textureReceiveID)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
# copy data into texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, spoutReceiverWidth, spoutReceiverHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, None )
glBindTexture(GL_TEXTURE_2D, 0)
# initalise sender texture
glBindTexture(GL_TEXTURE_2D, textureStyleID);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glBindTexture(GL_TEXTURE_2D, 0)
# open tf session
soft_config = tf.ConfigProto(allow_soft_placement=True)
soft_config.gpu_options.allow_growth = True # to deal with large image
sess = tf.Session(config=soft_config)
# build tf graph
style = tf.placeholder(tf.float32, shape=[spoutReceiverHeight, spoutReceiverWidth, 3], name='input')
styleI = tf.expand_dims(style, 0) # add one dim for batch
# result image from transform-net
scaler = transform.Transform()
y_hat = scaler.net(styleI/255.0)
y_hat = tf.squeeze(y_hat) # remove one dim for batch
y_hat = tf.clip_by_value(y_hat, 0., 255.)
# initialize parameters
sess.run(tf.global_variables_initializer())
# load pre-trained model
saver = tf.train.Saver()
saver.restore(sess, args.style_model)
# loop for graph frame by frame
while(True):
for event in pygame.event.get():
if event.type == pygame.QUIT:
spoutReceiver.ReleaseReceiver()
pygame.quit()
quit()
# receive texture
# Its signature in c++ looks like this: bool pyReceiveTexture(const char* theName, unsigned int theWidth, unsigned int theHeight, GLuint TextureID, GLuint TextureTarget, bool bInvert, GLuint HostFBO);
spoutReceiver.pyReceiveTexture(receiverName, spoutReceiverWidth, spoutReceiverHeight, textureReceiveID, GL_TEXTURE_2D, False, 0)
glBindTexture(GL_TEXTURE_2D, textureReceiveID)
# copy pixel byte array from received texture
data = glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, outputType=None) #Using GL_RGB can use GL_RGBA
glBindTexture(GL_TEXTURE_2D, 0)
# swap width and height data around due to oddness with glGetTextImage. http://permalink.gmane.org/gmane.comp.python.opengl.user/2423
data.shape = (data.shape[1], data.shape[0], data.shape[2])
# start time of the loop for FPS counter
start_time = time.time()
#run the graph
output = sess.run(y_hat, feed_dict={style: data})
# fiddle back to an image we can display. I *think* this is correct
output = np.clip(output, 0.0, 255.0)
output = output.astype(np.uint8)
# setup the texture so we can load the stylised output into it
glBindTexture(GL_TEXTURE_2D, textureStyleID)
# copy style output into texture
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, spoutReceiverWidth, spoutReceiverHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, output )
# setup window to draw to screen
glActiveTexture(GL_TEXTURE0)
# clean start
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT )
# reset drawing perspective
glLoadIdentity()
# draw texture on screen
glBegin(GL_QUADS)
glTexCoord(0,0)
glVertex2f(0,0)
glTexCoord(1,0)
glVertex2f(spoutReceiverWidth,0)
glTexCoord(1,1)
glVertex2f(spoutReceiverWidth,spoutReceiverHeight)
glTexCoord(0,1)
glVertex2f(0,spoutReceiverHeight)
glEnd()
# update window
pygame.display.flip()
# FPS = 1 / time to process loop
print("FPS: ", 1.0 / (time.time() - start_time))
if __name__ == '__main__':
main()