Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

273 ia nsfw flag #409

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions upload/actions/test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

define('THIS_PAGE', 'launch_tool');

require_once dirname(__FILE__, 2) . '/includes/admin_config.php';
require_once('../includes/classes/admin_tool.class.php');
require_once('../includes/classes/AIVision.class.php');

/** Set the directory where the library will be downloaded, if it not set then it will be stored inside vendor directory */
Onnx\Library::setFolder(__DIR__.'/../ai/');

/** Download the library if not found */
Onnx\Library::install();

/** definition du model et de ses parametres */
$ia = new AIVision([
'tags' => [ 0 => "Naked", 1 => "Safe"]
,'rescale_factor' => 0.00392156862745098
,'format' => 'rgb'
,'height' => 224
,'width' => 224
,'shape' => 'bhwc' /* batch channel height width */
,'modelNameOrPath' => __DIR__.'/../ai/models/model.onnx'// https://huggingface.co/suko/nsfw
]);

/** Load models */
$ia->loadModel();

/** analyse one image */
$tags = $ia->getTags(__DIR__.'/../ai/images/test_image.jpg');

var_dump($tags);
16 changes: 8 additions & 8 deletions upload/admin_area/styles/cb_2014/layout/system_info.html
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,13 @@ <h3>PHP CLI</h3>
{foreach $php_extensions_list as $key => $extension}
<div class="row ml-2">
<div class="col-lg-10">
<img src="{$imageurl}/{if $extensionsWEB.$key}tick{else}alert{/if}.png"/>
<img src="{$imageurl}/{if in_array($key,$extensionsWEB)}tick{else}alert{/if}.png"/>
<label>
{$extension.display} extension -
{if !$extensionsWEB.$key}
{$extension.display} extension
{if !in_array($key,$extensionsWEB)}
<div class="alert alert-danger">{lang code='not_found'}</div>
{else}
<strong>{$extensionsWEB.$key}</strong>
<strong>enabled</strong>
{/if}
</label>
</div>
Expand Down Expand Up @@ -119,13 +119,13 @@ <h3>PHP CLI</h3>
{foreach $php_extensions_list as $key => $extension}
<div class="row ml-2">
<div class="col-lg-10">
<img src="{$imageurl}/{if $extensionsCLI.$key}tick{else}alert{/if}.png"/>
<img src="{$imageurl}/{if in_array($key,$extensionsCLI)}tick{else}alert{/if}.png"/>
<label>
{$extension.display} extension -
{if !$extensionsCLI.$key}
{$extension.display} extension
{if !in_array($key,$extensionsCLI)}
<div class="alert alert-danger">{lang code='not_found'}</div>
{else}
<strong>{$extensionsCLI.$key}</strong>
<strong>enabled</strong>
{/if}
</label>
</div>
Expand Down
Binary file added upload/ai/images/test_image.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions upload/ai/models/readme
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
telecharger le fichier model.onnx depuis le site : https://huggingface.co/suko/nsfw et le placer dans ce dossier
13 changes: 9 additions & 4 deletions upload/cb_install/modes/precheck.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,16 @@
}
$line++;

if( empty($php_extensions[$key]) ) {
$everything_good = false;
$msg = ['err' => $extension['display'] . ' extension is not enabled'];
if( !in_array($key, $php_extensions, true) ) {
$txt = ' extension is not enabled';
if( $key == 'ffi' ){
$msg = ['war' => $extension['display'] . $txt];
} else {
$everything_good = false;
$msg = ['err' => $extension['display'] . $txt];
}
} else {
$msg = ['msg' => $extension['display'] . ' extension '. $php_extensions[$key]];
$msg = ['msg' => $extension['display'] . ' extension enabled'];
}

echo '<dt' . ($line %2 == 0 ? ' class=\'white\'' : '') . '><span>' . $extension['display'] . '</dt>';
Expand Down
4 changes: 3 additions & 1 deletion upload/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
"oxygenzsas/composer_lib_discord": "dev-php7",
"psr/http-server-middleware": "1.0.2",
"ext-json": "*",
"ext-mysqli": "*"
"ext-mysqli": "*",
"ext-ffi": "*",
"veka-server/onnx-php": "dev-php7"
},
"config": {
"platform": {
Expand Down
207 changes: 207 additions & 0 deletions upload/includes/classes/AIVision.class.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
<?php

use Onnx\DType;
use Onnx\Tensor;

class AIVision
{
protected $tags = [ 0 => "Naked", 1 => "Safe"];
protected $rescale_factor = 0.00392156862745098 ;
protected $format = 'rgb';
protected $height = 224;
protected $width = 224;
protected $shape = 'bhwc'; /* batch channel height width */
protected $modelNameOrPath ;

protected $provider = 'CPUExecutionProvider';
protected $model;

public function __construct(array $config = [], $lib = null) {

if(!empty($config)) {
$this->tags = $config['tags'] ?? [] ;
$this->rescale_factor = $config['rescale_factor'] ?? 1 ;
$this->modelNameOrPath = $config['modelNameOrPath'] ?? null ;
$this->format = $config['format'] ?? 'rgb' ;
$this->height = $config['height'] ?? 2 ;
$this->width = $config['width'] ?? 256 ;
$this->shape = $config['shape'] ?? 'bchw' ;
}

if(!empty($lib)) {

if(!is_file($lib)) {
throw new \Exception( 'Unable to find the lib file : ' . dirname($lib) );
}

\Onnx\FFI::$lib = $lib;

if (\FFI\WorkDirectory\WorkDirectory::set(dirname($lib)) === false) {
throw new \Exception( 'FAILED to CWD has been updated to: ' . dirname($lib) );
}

}
}

public function loadModel($model = null) {
if(!empty($model)) {
$this->modelNameOrPath = $model;
}

if(empty($this->modelNameOrPath)) {
throw new \Exception('model missing');
}

/** chargement du model */
$this->model = new \Onnx\Model($this->modelNameOrPath);
}

/**
* @throws \Exception
*/
public static function createImageGDFromPath($path) {

$pathParts = pathinfo( $path);
switch ( strtolower($pathParts["extension"])) {
case 'png':
$image = imagecreatefrompng($path);
break;
case 'jpg':
case 'jpeg':
$image = imagecreatefromjpeg($path);
break;
case 'gif':
$image = imagecreatefromgif($path);
break;
default:
throw new \Exception('Format de fichier non reconnu');
}

return $image;
}

public static function getGDImageFromImg($image, $width, $height)
{
$img = self::createImageGDFromPath($image);

if(imagesx($img) > imagesy($img)) {
$reduction = imagesx($img) / $width;
} else {
$reduction = imagesy($img) / $height;
}

/** converti l'image en $this->dimenssion_imagex$this->dimenssion_image */
$image2 = imagecreatetruecolor($width, $height); /* dimmension fixe */
imagefill($image2,0,0,0x7fff0000); /* remplir avec de la transparence */
imagecopyresampled($image2, $img, 0, 0, 0, 0, floor(imagesx($img)/$reduction), floor(imagesy($img)/$reduction), imagesx($img), imagesy($img)); /* copier l'image */

return $image2;
}

public static function getPixels($img, $format = 'rgb', $rescale_factor = 1)
{
$pixels = [];
$width = imagesx($img);
$height = imagesy($img);

// Mapping for different formats
$formats = [
'bgr' => ['blue', 'green', 'red'],
'rgb' => ['red', 'green', 'blue'],
];

// Ensure the format exists, otherwise default to 'rgb'
$format = isset($formats[strtolower($format)]) ? $formats[strtolower($format)] : $formats['rgb'];

for ($y = 0; $y < $height; $y++) {
$row = [];
for ($x = 0; $x < $width; $x++) {
$rgb = imagecolorat($img, $x, $y);
$color = imagecolorsforindex($img, $rgb);
$row[] = [
$color[$format[0]] * $rescale_factor,
$color[$format[1]] * $rescale_factor,
$color[$format[2]] * $rescale_factor
];
}
$pixels[] = $row;
}
return $pixels;
}

public function getTags($image){

/** resize de l'image pour qu'elle soit dans le bon format */
$img = self::getGDImageFromImg( $image, $this->width, $this->height );

/** Extraction des pixels */
$pixels = self::getPixels($img, $this->format, $this->rescale_factor);

/** converti le shape */
$pixels = $this->transposeImage([$pixels], $this->shape);

/** Récuperation du nom de l'input depuis le model */
$input_name = $this->model->inputs()[0]['name'];

$tensor = Tensor::fromArray($pixels,DType::FLOAT32);

/** prediction IA */
$result = $this->model->predict([$input_name => $tensor]);

$clean_result = $this->postprocess($result);

return $clean_result;
}

function transposeImage($pixels, $format = 'bhwc') {

if(strtolower($format) == 'bhwc') {
return $pixels;
}

$transposedImage = [];

if($format == 'bchw') {
foreach ($pixels as $b => $batch) {
foreach ($batch as $h => $row) {
foreach ($row as $w => $pixel) {
foreach ($pixel as $c => $value) {
$transposedImage[$b][$c][$h][$w] = $value;
}
}
}
}
}

return $transposedImage;
}

protected function postprocess($result) {

$t = [];
$output_name = $this->model->outputs()[0]['name'];

foreach ($result[$output_name][0] as $idx => $v) {

if(empty($this->tags[$idx])) {
continue;
}

$t[$this->tags[$idx]] = $v;

}

return $t;
}

public function setProvider(string $provider = null)
{
if(empty($provider)) {
$this->provider = 'CPUExecutionProvider';
return ;
}

$this->provider = $provider;
}

}
59 changes: 6 additions & 53 deletions upload/includes/classes/system.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,48 +9,7 @@ private static function init_php_extensions($type, $custom_filepath = null)
{
switch($type){
case 'php_web':
ob_start();
phpinfo(INFO_MODULES);
$s = ob_get_contents();
ob_end_clean();

$s = strip_tags($s, '<h2><th><td>');
$s = preg_replace('/<th[^>]*>([^<]+)<\/th>/', "<info>\\1</info>", $s);
$s = preg_replace('/<td[^>]*>([^<]+)<\/td>/', "<info>\\1</info>", $s);
$vTmp = preg_split('/(<h2>[^<]+<\/h2>)/', $s, -1, PREG_SPLIT_DELIM_CAPTURE);
$vModules = [];
for ($i = 1; $i < count($vTmp); $i++) {
if (preg_match('/<h2>([^<]+)<\/h2>/', $vTmp[$i], $vMat)) {
$vName = trim($vMat[1]);
$vTmp2 = explode("\n", $vTmp[$i + 1]);
foreach ($vTmp2 as $vOne) {
$vPat = '<info>([^<]+)<\/info>';
$vPat3 = "/$vPat\s*$vPat\s*$vPat/";
$vPat2 = "/$vPat\s*$vPat/";
if (preg_match($vPat3, $vOne, $vMat)) { // 3cols
$vModules[$vName][trim($vMat[1])] = [
trim($vMat[2]),
trim($vMat[3])
];
} elseif (preg_match($vPat2, $vOne, $vMat)) { // 2cols
$vModules[$vName][trim($vMat[1])] = trim($vMat[2]);
}
}
}
}

$regex_version = '(\d+\.\d+\.\d+)';
$php_extensions = self::get_php_extensions_list();
foreach($php_extensions as $key => $extension){
foreach($extension['version_tags'] as $tag){
if (!empty($vModules[$key][$tag]) && empty(self::$extensionsWeb[$key])) {
$matches = [];
preg_match($regex_version, $vModules[$key][$tag], $matches);
self::$extensionsWeb[$key] = $matches[0]??$vModules[$key][$tag];
}
}
}

self::$extensionsWeb = array_map('strtolower', get_loaded_extensions());
break;

case 'php_cli':
Expand Down Expand Up @@ -83,17 +42,7 @@ private static function init_php_extensions($type, $custom_filepath = null)
}

foreach($php_extensions as $key => $extension){
foreach($extension['version_tags'] as $tag){
if (strpos($line, $tag) !== false) {
$line = explode('=>', $line);
$tmp_version = trim(end($line));

preg_match($regex_version, $tmp_version, $match_version);
self::$extensionsCli[$key] = $match_version[0] ?? $tmp_version;

continue 3;
}
}
self::$extensionsCli[] = $key;
}

}
Expand Down Expand Up @@ -136,6 +85,10 @@ public static function get_php_extensions_list(): array
'fileinfo' => [
'display' => 'Fileinfo'
,'version_tags' => ['fileinfo support']
],
'ffi' => [
'display' => 'FFI'
,'version_tags' => ['FFI support']
]
];
}
Expand Down
Loading