Let's implement a software based on Laravel that executes Python from PHP and displays the result of image recognition.
The implementation of image recognition is Try learning MNIST with TensorFlow, which is based on the separate learning and testing. To.
[2020/4/15] Introduced Bootstrap in view
--OS: Ubuntu 18.04.4 LTS (on Virtual BOX)
Python3, which is included in Ubuntu 18.04.4 LTS by default, was 3.6.9, so I have updated it. At the same time, include the library used in Python.
$sudo apt install python3.8
$sudo apt-get install python3-pip python3-dev
$pip3 install tensorflow
$pip3 install numpy
$pip3 install opencv-python
Note that if you install with the $ sudo apt-get install python-pip python-dev
and pip
commands, the Python2 library will be included.
Rewrite "~ / .bashrc" to use python3.8.
..bashrc
alias python3='/usr/bin/python3.8'
Create a project named laravelAI.
$ composer create-project laravel/laravel laravelAI --prefer-dist
Only the items to be added / corrected this time are listed. The deficit is added. laravelAI ┗ app ┗ Http ┗ MnistController.php ┗ Python </ font>: Stores Python related files ┗ mnist_test.py ┗ DeepConvNet.py ┗ ckpt </ font>: Store learning results ┗ resources ┗ views ┗ mnist ┗ index.blade.php ┗ routes ┗ wab.php
Create a controller.
$ php artisan make:controller MnistController
MnistController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class MnistController extends Controller
{
public function index(Request $request)
{
$data = [
'msg' => "Please enter an image",
];
return view('mnist.index', $data);
}
public function test(Request $request)
{
if(!empty($request->test_image))
{
//Get the image sent by POST
$image = $request->file('test_image');
//The save destination is"storage/app/public/image"Will be
//File name will be assigned automatically
$up_pass = $image->store('public/image');
$image_pass = "./storage/image/".basename($up_pass);
//Set the path where the Python file is
$pythonPath = "../app/Python/";
$command = "/usr/bin/python3 " . $pythonPath . "mnist_test.py " . $pythonPath . " " .$image_pass;
exec($command , $outputs);
//Extracting result rows with regular expressions
$results = preg_grep('/result:.*/' , $outputs);
if(count($results) == 1){
//Get the beginning of an associative array
$result = reset($results);
$result = substr($result , strlen('result:') , 1 );
}
else {
$result = "Analysis failed.";
}
$data = [
'msg' => "Do you have a?",
'image_pass' => $image_pass,
'result' => $result,
'lines' => count($outputs),
'outputs' => $outputs,
];
}
else {
$data = [
'msg' => "there is no image",
];
}
return view('mnist.index', $data);
}
}
//Set the path where the Python file is
$pythonPath = "../app/Python/";
$command = "/usr/bin/python3 " . $pythonPath . "mnist_test.py " . $pythonPath . " " .$image_pass;
exec($command , $outputs);
Executing commands from PHP uses the ʻexec ()` function. Specify the command to be executed in the first argument, and specify the variable that stores the output result of the command in the second argument. See here for details.
Run Python in the / usr / bin / python3 Python file
.
The $ command
string above looks like this:
/usr/bin/python3 ../app/Python/mnist_test.py ../app/Python/ ./storage/image/FxY92Ji6j04cyozrx62yGHu9NQzLgsIqQq23YIcH.png
If you modify the command as $ command =" pwd ";
and execute it, you can see that the execution path of Laravel is "/ home / hogehoge / laravelAI / public". Assuming that, specify the location where the Python file is located.
"Learning data path" is specified in the first argument of mnist_test.py
, and" image path "is specified in the second argument.
//Get the image sent by POST
$image = $request->file('test_image');
$up_pass = $image->store('public/image');
$image_pass = "./storage/image/".basename($up_pass);
The image will be saved in "storage / app / public / image".
Make a symbolic link from "public / storage" to "storage / app / public" with the following command. For the second argument of mnist_test.py
and the image displayed in the view, specify the path under" public / storage ".
$ php artisan storage:link
$ cd public
$ ls -la
=> storage -> /home/hogehoge/laravelAI/storage/app/public
Add the following to routes / web.php
.
routes/web.php
Route::get ('mnist', 'MnistController@index');
Route::post('mnist', 'MnistController@test');
Pyhton As for the learning result, the one of Try learning MNIST with TensorFlow can be used as it is. Store it in the "Python / ckpt" folder.
The test code will be modified slightly. Allows you to specify "training data path" and "image path" with command line arguments.
mnist_test.py
# -*- coding: utf-8 -*-
print('mnist_test.py START')
import sys
import tensorflow as tf
import cv2
import numpy as np
import DeepConvNet as CNN
#Get command line arguments
args = sys.argv
IMAGE_SIZE = 28 #Image size
NUM_CLASSES = 10 #Number of identifications
if __name__ == "__main__":
tf.reset_default_graph()
print('Setting START')
#Variable settings used in expressions
x_image = tf.placeholder("float", shape=[None, IMAGE_SIZE * IMAGE_SIZE]) #input
y_label = tf.placeholder("float", shape=[None, NUM_CLASSES]) #output
keep_prob = tf.placeholder("float")
#Create a model
logits = CNN.CNN.makeMnistCNN(x_image, keep_prob , IMAGE_SIZE , NUM_CLASSES)
sess = tf.InteractiveSession()
saver = tf.train.Saver()
#Initialize and execute variables
sess.run(tf.global_variables_initializer())
print('Setting END')
print('Restore Param Start')
ckpt = tf.train.get_checkpoint_state(args[1] + 'ckpt')
#print(os.path.exists(args[1] + 'ckpt'))
if ckpt: #If there is a checkpoint
last_model = ckpt.model_checkpoint_path #Path to the last saved model
print ("Restore load:" + last_model)
saver.restore(sess, last_model) #Reading variable data
else:
print('Restore Failed')
print('Restore Param End')
#Image loading
inputNum = 1
for count in range(int(inputNum)):
fileName = args[2]
print('fileName:' + fileName)
#Initialization
ximage = []
#Image loading
image = cv2.imread(fileName, cv2.IMREAD_GRAYSCALE)
if not image is None:
image = cv2.resize(image, (IMAGE_SIZE, IMAGE_SIZE))
ximage = image.flatten().astype(np.float32)/255.0
else:
print('Error:File Read Failed !!')
if len(ximage)!=0:
pred = np.argmax(logits.eval(feed_dict={x_image: [ximage], keep_prob: 1.0})[0])
print("result:" + str(pred))
sess.close()
print('mnist_test.py END')
Create a view. The layout is suitable.
index.blade.php //.html
<html>
<head>
<title>Mnist</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" >
<style>
body{
background-color: #EEFFEE;
}
</style>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-sm-10">
<h2>1-Recognize the number 9</h2>
<p>{{$msg}}</p>
<form method = "POST" action="/mnist" enctype="multipart/form-data">
@csrf
<input type="file" name="test_image"><BR>
<input type="submit" id="submit" value="Send">
</form>
</div>
</div>
<div class="row">
@isset($image_pass)
<div class="col-sm-5">
<h3>result</h3>
<img src="{{ asset($image_pass)}}" width="112" height="112"> <BR>
@isset($result)
<p>This image is "{{$result}}"is</p>
@endempty
</div>
@endempty
@isset($outputs)
<div class="col-sm-5">
<h3>Python output( {{$lines}}line)</h3>
@foreach ($outputs as $output)
{{$output}}<BR>
@endforeach
</div>
@endempty
</div>
</div>
</body>
</html>
Start the server with the following command.
$ php artisan serve
Go to "http: // localhost: 8000 / mnist" in your browser.
Select a file and send it.
I was able to recognize it!
The introduction of Vue and TypeScript is described in PHP and Python integration from scratch on Laravel + Vue + TypeScript.
When I was messing with the code in another case, I ran into the above exception with $ image-> store ()
in the file save, so I caught it.
Symfony\Component\Mime\Exception\InvalidArgumentException
The "" file does not exist or is not readable.
It's hard to tell from the exception message or call stack, but it's because you're stuck with an uploaded file size limit.
The file size is defined in the php.ini file, so modify it.
(I searched online and found a way to fix .htaccess, but fixing public / .htaccess
didn't help.)
# php.Check the location of ini
$ php -i | grep php.ini
Configuration File (php.ini) Path => /etc/php/7.2/cli
Loaded Configuration File => /etc/php/7.2/cli/php.ini
$ sudo vi /etc/php/7.2/cli/php.ini
Modify the following two lines as needed. In PHP7.2, it defaults to 2MB and 8MB.
php.ini
;Maximum total size of all files uploaded by POST
post_max_size=2M
;Maximum size per file
upload_max_filesize=8M
Please restart the server after making the change.
$ php artisan serve
Recommended Posts