Skip to content

Commit 8cffe30

Browse files
committed
Add stylization
1 parent 078a23a commit 8cffe30

File tree

2 files changed

+132
-0
lines changed

2 files changed

+132
-0
lines changed

example-style.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
require __DIR__.'/vendor/autoload.php';
3+
4+
/**
5+
* Configuration
6+
* We need some files (tensorflow itself, and the tensorflow models) to be able
7+
* to use FuncAI. Downloading these files happens automatically, but you need
8+
* to provide folders where we can store those files.
9+
*
10+
* These folders will have to be available on your production server
11+
* and we will store about 300 Mb of data in them.
12+
*/
13+
14+
// Specify where the tensorflow models should be stored
15+
\FuncAI\Config::setModelBasePath(realpath(dirname(__FILE__) . '/models/'));
16+
// Specify where tensorflow should be downloaded to
17+
\FuncAI\Config::setLibPath(dirname(__FILE__) . '/tensorflow/');
18+
19+
20+
/**
21+
* Installation
22+
* This downloads all necessary files and makes sure they are set up correctly.
23+
*/
24+
$tfi = new \FuncAI\Install\TensorflowInstaller();
25+
$tfi->install();
26+
27+
28+
/**
29+
* Prediction
30+
* This is a sample prediction which uses the efficientNet model to determine the contents
31+
* of an image.
32+
*/
33+
$model = new \FuncAI\Models\Stylization();
34+
#$model->printGraph();
35+
$output = $model->predict([
36+
__DIR__ . '/sample_data/mona-lisa.jpg',
37+
__DIR__ . '/sample_data/style5.jpg',
38+
]);
39+
# var_dump($output);

src/Models/Stylization.php

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<?php
2+
namespace FuncAI\Models;
3+
4+
use FuncAI\Config;
5+
use FuncAI\Tensorflow\TensorFlow;
6+
7+
class Stylization extends AbstractModel
8+
{
9+
/**
10+
* @var int
11+
*/
12+
private $width;
13+
/**
14+
* @var int
15+
*/
16+
private $height;
17+
18+
public function getModelPath()
19+
{
20+
return Config::getModelBasePath() . '/arbitrary-image-stylization';
21+
}
22+
23+
public function getOutputTensor()
24+
{
25+
$output = $this->tf->getDefaultGraph()->operation('StatefulPartitionedCall')->output(0);
26+
27+
return $output;
28+
}
29+
30+
public function getInputData($input)
31+
{
32+
return [
33+
'serving_default_placeholder' => $this->toImageTensor($input[0], true),
34+
'serving_default_placeholder_1' => $this->toImageTensor($input[1], true),
35+
];
36+
}
37+
38+
private function toImageTensor($path, $resize = false)
39+
{
40+
$img = imagecreatefromjpeg($path);
41+
if($resize) {
42+
$img = imagescale($img, 256, 256);
43+
}
44+
$this->width = imagesx($img);
45+
$this->height = imagesy($img);
46+
$ret = $this->tf->tensor(null, TensorFlow::FLOAT, [1, $this->width, $this->height, 3]);
47+
$data = $ret->data();
48+
49+
// Convert the image data into a flat array
50+
for ($y = 0; $y < $this->height; $y++) {
51+
for ($x = 0; $x < $this->width; $x++) {
52+
$rgb = imagecolorat($img, $x, $y);
53+
$r = ($rgb >> 16) & 0xFF;
54+
$g = ($rgb >> 8) & 0xFF;
55+
$b = $rgb & 0xFF;
56+
$idx = ($y * $this->width * 3) + ($x * 3);
57+
$data[$idx] = (float)($r/255);
58+
$data[$idx + 1] = (float)($g/255);
59+
$data[$idx + 2] = (float)($b/255);
60+
}
61+
}
62+
return $ret;
63+
}
64+
65+
public function getInputLayer()
66+
{
67+
return 'serving_default_input_0';
68+
}
69+
70+
protected function transformResult($result)
71+
{
72+
return $this->saveImage($result);
73+
}
74+
75+
private function saveImage($imageData)
76+
{
77+
$imageData = $imageData[0];
78+
$w = count($imageData);
79+
$h = count($imageData[0]);
80+
$img = imagecreatetruecolor($w, $h);
81+
foreach($imageData as $y => $row) {
82+
foreach($row as $x => $color) {
83+
$color = array_map(function($c) {
84+
$c *= 255;
85+
return min(255,max(0,$c));
86+
}, $color);
87+
$c = imagecolorallocate($img, $color[0], $color[1], $color[2]);
88+
imagesetpixel($img, $x, $y, $c);
89+
}
90+
}
91+
imagejpeg($img, 'out.jpg');
92+
}
93+
}

0 commit comments

Comments
 (0)