mirror of
https://github.com/Karaka-Management/phpOMS.git
synced 2026-01-11 17:58:41 +00:00
update cmd handling, fix bugs
This commit is contained in:
parent
a86685a04d
commit
755ee54f0c
|
|
@ -15,6 +15,7 @@ declare(strict_types=1);
|
|||
namespace phpOMS\Ai\Ocr\Tesseract;
|
||||
|
||||
use phpOMS\System\File\PathException;
|
||||
use phpOMS\System\SystemUtils;
|
||||
|
||||
/**
|
||||
* Tesseract api
|
||||
|
|
@ -54,87 +55,6 @@ final class TesseractOcr
|
|||
self::$bin = \realpath($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run git command.
|
||||
*
|
||||
* @param string $cmd Command to run
|
||||
*
|
||||
* @return string[]
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function run(string $cmd) : array
|
||||
{
|
||||
if (\strtolower((string) \substr(\PHP_OS, 0, 3)) === 'win') {
|
||||
$cmd = 'cd ' . \escapeshellarg(\dirname(self::$bin))
|
||||
. ' && ' . \basename(self::$bin)
|
||||
. ' '
|
||||
. $cmd;
|
||||
} else {
|
||||
$cmd = \escapeshellarg(self::$bin)
|
||||
. ' '
|
||||
. $cmd;
|
||||
}
|
||||
|
||||
$pipes = [];
|
||||
$desc = [
|
||||
1 => ['pipe', 'w'],
|
||||
2 => ['pipe', 'w'],
|
||||
];
|
||||
|
||||
$resource = \proc_open($cmd, $desc, $pipes, null, null);
|
||||
|
||||
if ($resource === false) {
|
||||
throw new \Exception();
|
||||
}
|
||||
|
||||
$stdout = \stream_get_contents($pipes[1]);
|
||||
$stderr = \stream_get_contents($pipes[2]);
|
||||
|
||||
foreach ($pipes as $pipe) {
|
||||
\fclose($pipe);
|
||||
}
|
||||
|
||||
$status = \proc_close($resource);
|
||||
|
||||
if ($status == -1) {
|
||||
throw new \Exception((string) $stderr);
|
||||
}
|
||||
|
||||
return $this->parseLines(\trim($stdout === false ? '' : $stdout));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse lines.
|
||||
*
|
||||
* @param string $lines Result of git command
|
||||
*
|
||||
* @return string[]
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function parseLines(string $lines) : array
|
||||
{
|
||||
$lineArray = \preg_split('/\r\n|\n|\r/', $lines);
|
||||
$lines = [];
|
||||
|
||||
if ($lineArray === false) {
|
||||
return $lines;
|
||||
}
|
||||
|
||||
foreach ($lineArray as $line) {
|
||||
$temp = \preg_replace('/\s+/', ' ', \trim($line, ' '));
|
||||
|
||||
if (!empty($temp)) {
|
||||
$lines[] = $temp;
|
||||
}
|
||||
}
|
||||
|
||||
return $lines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prase image
|
||||
*
|
||||
|
|
@ -167,7 +87,8 @@ final class TesseractOcr
|
|||
*/
|
||||
public function parseImage(string $image, array $languages = ['eng'], int $psm = 3, int $oem = 3) : string
|
||||
{
|
||||
$this->run(
|
||||
SystemUtils::runProc(
|
||||
self::$bin,
|
||||
$image . ' '
|
||||
. ($temp = \tempnam(\sys_get_temp_dir(), 'ocr_'))
|
||||
. ' --psm ' . $psm
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ final class Skew
|
|||
|
||||
$avg /= $start[1] - $end[1];
|
||||
|
||||
$dimImMatrix = [$end[0] - $start[0], $end[1] - $start[1]];
|
||||
$dimImMatrix = [\count($imMatrix), \count($imMatrix[0])];
|
||||
$bestScore = 0;
|
||||
$bestDegree = 0;
|
||||
|
||||
|
|
@ -77,7 +77,7 @@ final class Skew
|
|||
$rotated = self::rotatePixelMatrix($imMatrix, $dimImMatrix, $i);
|
||||
$hist = [];
|
||||
|
||||
for ($j = 0; $j < $dimImMatrix[1]; ++$j) {
|
||||
for ($j = 0; $j < $dimImMatrix[0]; ++$j) {
|
||||
$hist[$j] = \array_sum($rotated[$j]);
|
||||
|
||||
// cleanup for score function
|
||||
|
|
@ -95,8 +95,6 @@ final class Skew
|
|||
|
||||
$im = \imagerotate($im, $bestDegree, 1);
|
||||
|
||||
// https://stackoverflow.com/questions/29981083/rotating-a-bit-matrix
|
||||
|
||||
if (\strripos($outPath, 'png') !== false) {
|
||||
\imagepng($im, $outPath);
|
||||
} elseif (\strripos($outPath, 'jpg') !== false || \strripos($outPath, 'jpeg') !== false) {
|
||||
|
|
@ -118,13 +116,13 @@ final class Skew
|
|||
$rotated = [[]];
|
||||
|
||||
for ($i = 0; $i < $dim[0]; ++$i) {
|
||||
$cY = $i - $dim[1] / 2.0; // center
|
||||
$cY = $i - $dim[0] / 2.0; // center
|
||||
|
||||
for ($j = 0; $j < $dim[1]; ++$j) {
|
||||
$cX = $j - $dim[0] / 2.0; // center
|
||||
$cX = $j - $dim[1] / 2.0; // center
|
||||
|
||||
$x = $cos * $cX + $sin * $cY + $dim[0] / 2.0;
|
||||
$y = -$sin * $cX + $cos * $cY + $dim[1] / 2.0;
|
||||
$x = $cos * $cX + $sin * $cY + $dim[1] / 2.0;
|
||||
$y = -$sin * $cX + $cos * $cY + $dim[0] / 2.0;
|
||||
|
||||
$rotated[$i][$j] = self::getNearestValue($pixel, $dim, $x, $y);
|
||||
}
|
||||
|
|
@ -135,11 +133,11 @@ final class Skew
|
|||
|
||||
private static function getNearestValue(array $pixel, array $dim, float $x, float $y) : int
|
||||
{
|
||||
$xLow = \min((int) $x, $dim[0] - 1);
|
||||
$xHigh = \min((int) \ceil($x), $dim[0] - 1);
|
||||
$xLow = \min((int) $x, $dim[1] - 1);
|
||||
$xHigh = \min((int) \ceil($x), $dim[1] - 1);
|
||||
|
||||
$yLow = \min((int) $y, $dim[1] - 1);
|
||||
$yHigh = \min((int) \ceil($y), $dim[1] - 1);
|
||||
$yLow = \min((int) $y, $dim[0] - 1);
|
||||
$yHigh = \min((int) \ceil($y), $dim[0] - 1);
|
||||
|
||||
$points = [
|
||||
[$xLow, $yLow],
|
||||
|
|
|
|||
|
|
@ -54,12 +54,8 @@ final class Thresholding
|
|||
$out = \imagecreate($dim[0], $dim[1]);
|
||||
|
||||
$intImg = [[]];
|
||||
|
||||
$s = (int) $dim[0] / 96; // can be changed 8
|
||||
$t = 30; // can be changed 15
|
||||
|
||||
for ($i = 0; $i < $dim[0]; ++$i) {
|
||||
$sum = 0;
|
||||
$sum = 0.0;
|
||||
|
||||
for ($j = 0; $j < $dim[1]; ++$j) {
|
||||
$rgb = \imagecolorat($im, $i, $j);
|
||||
|
|
@ -69,16 +65,19 @@ final class Thresholding
|
|||
}
|
||||
}
|
||||
|
||||
$s = (int) ($dim[0] / 96.0); // can be changed 8
|
||||
$t = 30; // can be changed 15
|
||||
|
||||
$black = \imagecolorallocate($out, 0, 0, 0);
|
||||
$white = \imagecolorallocate($out, 255, 255, 255);
|
||||
|
||||
for ($i = 0; $i < $dim[0]; ++$i) {
|
||||
for ($j = 0; $j < $dim[1]; ++$j) {
|
||||
$x1 = \max(1, (int) ($i - $s / 2));
|
||||
$x2 = \min((int) ($i + $s / 2), $dim[0] - 1);
|
||||
$x1 = \max(1, (int) ($i - $s / 2.0));
|
||||
$x2 = \min((int) ($i + $s / 2.0), $dim[0] - 1);
|
||||
|
||||
$y1 = \max(1, (int) ($j - $s / 2));
|
||||
$y2 = \min((int) ($j + $s / 2), $dim[1] - 1);
|
||||
$y1 = \max(1, (int) ($j - $s / 2.0));
|
||||
$y2 = \min((int) ($j + $s / 2.0), $dim[1] - 1);
|
||||
|
||||
$count = ($x2 - $x1) * ($y2 - $y1);
|
||||
$sum = $intImg[$x2][$y2] - $intImg[$x2][$y1 - 1] - $intImg[$x1 - 1][$y2] + $intImg[$x1 - 1][$y1 - 1];
|
||||
|
|
@ -86,7 +85,7 @@ final class Thresholding
|
|||
$rgb = \imagecolorat($im, $i, $j);
|
||||
$brightness = ImageUtils::lightness($rgb);
|
||||
|
||||
$color = $brightness * $count <= ($sum * (100 - $t) / 100) ? $black : $white;
|
||||
$color = $brightness * $count <= ($sum * (100.0 - $t) / 100.0) ? $black : $white;
|
||||
|
||||
\imagesetpixel($out, $i, $j, $color);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,12 +76,7 @@ final class HttpRequest extends RequestAbstract
|
|||
{
|
||||
$this->header = new HttpHeader();
|
||||
$this->header->l11n = $l11n ?? new Localization();
|
||||
|
||||
if ($uri !== null) {
|
||||
$this->uri = $uri;
|
||||
}
|
||||
|
||||
$this->init();
|
||||
$this->uri = $uri ?? new HttpUri('');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -93,13 +88,11 @@ final class HttpRequest extends RequestAbstract
|
|||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function init() : void
|
||||
public function initRequest() : void
|
||||
{
|
||||
if (!isset($this->uri)) {
|
||||
$this->initCurrentRequest();
|
||||
$this->lock();
|
||||
self::cleanupGlobals();
|
||||
}
|
||||
$this->initCurrentRequest();
|
||||
$this->lock();
|
||||
self::cleanupGlobals();
|
||||
|
||||
$this->data = \array_change_key_case($this->data, \CASE_LOWER);
|
||||
}
|
||||
|
|
@ -394,7 +387,10 @@ final class HttpRequest extends RequestAbstract
|
|||
*/
|
||||
public static function createFromSuperglobals() : self
|
||||
{
|
||||
return new self();
|
||||
$request = new self();
|
||||
$request->initRequest();
|
||||
|
||||
return $request;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -289,4 +289,9 @@ abstract class RequestAbstract implements MessageInterface
|
|||
{
|
||||
return $this->files;
|
||||
}
|
||||
|
||||
public function addFile(array $file) : void
|
||||
{
|
||||
$this->files[] = $file;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ With Karaka you have one partner who can provide all the tools and software solu
|
|||
- [Installation](#installation)
|
||||
- [Requirements](#requirements)
|
||||
- [Setup](#setup)
|
||||
- [End-User](#end-user)
|
||||
- [Developer](#developer)
|
||||
- [Philosophy](#philosophy)
|
||||
- [Development Status](#development-status)
|
||||
- [Features](#features)
|
||||
|
|
@ -86,6 +88,7 @@ Features this framework provides are:
|
|||
* Utils (e.g. barcodes, comporession, unit converter, jobqueue, git, etc.)
|
||||
* Value validation
|
||||
* View management
|
||||
* Image processing
|
||||
* Stdlib (e.g. graph, map, queue, enum, etc.)
|
||||
|
||||
## Unit Tests
|
||||
|
|
|
|||
|
|
@ -146,4 +146,62 @@ final class SystemUtils
|
|||
|
||||
return 'localhost.localdomain';
|
||||
}
|
||||
|
||||
public static function runProc(string $executable, string $cmd) : array
|
||||
{
|
||||
if (\strtolower((string) \substr(\PHP_OS, 0, 3)) === 'win') {
|
||||
$cmd = 'cd ' . \escapeshellarg(\dirname($executable))
|
||||
. ' && ' . \basename($executable)
|
||||
. ' '
|
||||
. $cmd;
|
||||
} else {
|
||||
$cmd = \escapeshellarg($executable)
|
||||
. ' '
|
||||
. $cmd;
|
||||
}
|
||||
|
||||
$pipes = [];
|
||||
$desc = [
|
||||
1 => ['pipe', 'w'],
|
||||
2 => ['pipe', 'w'],
|
||||
];
|
||||
|
||||
$resource = \proc_open($cmd, $desc, $pipes, null, null);
|
||||
|
||||
if ($resource === false) {
|
||||
throw new \Exception();
|
||||
}
|
||||
|
||||
$stdout = \stream_get_contents($pipes[1]);
|
||||
$stderr = \stream_get_contents($pipes[2]);
|
||||
|
||||
foreach ($pipes as $pipe) {
|
||||
\fclose($pipe);
|
||||
}
|
||||
|
||||
$status = \proc_close($resource);
|
||||
|
||||
if ($status == -1) {
|
||||
throw new \Exception((string) $stderr);
|
||||
}
|
||||
|
||||
$lines = \trim($stdout === false ? '' : $stdout);
|
||||
|
||||
$lineArray = \preg_split('/\r\n|\n|\r/', $lines);
|
||||
$lines = [];
|
||||
|
||||
if ($lineArray === false) {
|
||||
return $lines;
|
||||
}
|
||||
|
||||
foreach ($lineArray as $line) {
|
||||
$temp = \preg_replace('/\s+/', ' ', \trim($line, ' '));
|
||||
|
||||
if (!empty($temp)) {
|
||||
$lines[] = $temp;
|
||||
}
|
||||
}
|
||||
|
||||
return $lines;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -198,11 +198,13 @@ final class UriFactory
|
|||
private static function unique(string $url) : string
|
||||
{
|
||||
// handle edge cases / normalization
|
||||
/*
|
||||
$url = \str_replace(
|
||||
['=%', '=#', '=?'],
|
||||
['=%25', '=%23', '=%3F'],
|
||||
$url
|
||||
);
|
||||
*/
|
||||
|
||||
if (\stripos($url, '?') === false && ($pos = \stripos($url, '&')) !== false) {
|
||||
$url = \substr_replace($url, '?', $pos, 1);
|
||||
|
|
|
|||
|
|
@ -64,17 +64,17 @@ final class ImageUtils
|
|||
|
||||
public static function lightnessFromRgb(int $r, int $g, int $b) : float
|
||||
{
|
||||
$vR = $r / 255;
|
||||
$vG = $g / 255;
|
||||
$vB = $b / 255;
|
||||
$vR = $r / 255.0;
|
||||
$vG = $g / 255.0;
|
||||
$vB = $b / 255.0;
|
||||
|
||||
$lR = $vR <= 0.04045 ? $vR / 12.92 : \pow((($vR + 0.055) / 1.055), 2.4);
|
||||
$lG = $vG <= 0.04045 ? $vG / 12.92 : \pow((($vG + 0.055) / 1.055), 2.4);
|
||||
$lB = $vB <= 0.04045 ? $vB / 12.92 : \pow((($vB + 0.055) / 1.055), 2.4);
|
||||
|
||||
$y = 0.2126 * $lR + 0.7152 * $lG + 0.0722 * $lB;
|
||||
$lStar = $y <= 216 / 24389 ? $y * 24389 / 27 : \pow($y,(1 / 3)) * 116 - 16;
|
||||
$lStar = $y <= 216.0 / 24389.0 ? $y * 24389.0 / 27.0 : \pow($y, (1 / 3)) * 116.0 - 16.0;
|
||||
|
||||
return $lStar / 100;
|
||||
return $lStar / 100.0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,10 +30,11 @@ class Cron extends SchedulerAbstract
|
|||
*/
|
||||
public function create(TaskAbstract $task) : void
|
||||
{
|
||||
$this->run('-l > ' . __DIR__ . '/tmpcron.tmp');
|
||||
\file_put_contents(__DIR__ . '/tmpcron.tmp', $task->__toString() . "\n", \FILE_APPEND);
|
||||
$this->run(__DIR__ . '/tmpcron.tmp');
|
||||
\unlink(__DIR__ . '/tmpcron.tmp');
|
||||
$path = \tempnam(\sys_get_temp_dir(), 'cron_');
|
||||
$this->run('-l > ' . $path);
|
||||
\file_put_contents($path, $task->__toString() . "\n", \FILE_APPEND);
|
||||
$this->run($path);
|
||||
\unlink($path);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -41,10 +42,11 @@ class Cron extends SchedulerAbstract
|
|||
*/
|
||||
public function update(TaskAbstract $task) : void
|
||||
{
|
||||
$this->run('-l > ' . __DIR__ . '/tmpcron.tmp');
|
||||
$path = \tempnam(\sys_get_temp_dir(), 'cron_');
|
||||
$this->run('-l > ' . $path);
|
||||
|
||||
$new = '';
|
||||
$fp = \fopen(__DIR__ . '/tmpcron.tmp', 'r+');
|
||||
$fp = \fopen($path, 'r+');
|
||||
|
||||
if ($fp) {
|
||||
$line = \fgets($fp);
|
||||
|
|
@ -59,11 +61,11 @@ class Cron extends SchedulerAbstract
|
|||
}
|
||||
|
||||
\fclose($fp);
|
||||
\file_put_contents(__DIR__ . '/tmpcron.tmp', $new);
|
||||
\file_put_contents($path, $new);
|
||||
}
|
||||
|
||||
$this->run(__DIR__ . '/tmpcron.tmp');
|
||||
\unlink(__DIR__ . '/tmpcron.tmp');
|
||||
$this->run($path);
|
||||
\unlink($path);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -79,10 +81,11 @@ class Cron extends SchedulerAbstract
|
|||
*/
|
||||
public function deleteByName(string $name) : void
|
||||
{
|
||||
$this->run('-l > ' . __DIR__ . '/tmpcron.tmp');
|
||||
$path = \tempnam(\sys_get_temp_dir(), 'cron_');
|
||||
$this->run('-l > ' . $path);
|
||||
|
||||
$new = '';
|
||||
$fp = \fopen(__DIR__ . '/tmpcron.tmp', 'r+');
|
||||
$fp = \fopen($path, 'r+');
|
||||
|
||||
if ($fp) {
|
||||
$line = \fgets($fp);
|
||||
|
|
@ -97,11 +100,11 @@ class Cron extends SchedulerAbstract
|
|||
}
|
||||
|
||||
\fclose($fp);
|
||||
\file_put_contents(__DIR__ . '/tmpcron.tmp', $new);
|
||||
\file_put_contents($path, $new);
|
||||
}
|
||||
|
||||
$this->run(__DIR__ . '/tmpcron.tmp');
|
||||
\unlink(__DIR__ . '/tmpcron.tmp');
|
||||
$this->run($path);
|
||||
\unlink($path);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -109,10 +112,11 @@ class Cron extends SchedulerAbstract
|
|||
*/
|
||||
public function getAll() : array
|
||||
{
|
||||
$this->run('-l > ' . __DIR__ . '/tmpcron.tmp');
|
||||
$path = \tempnam(\sys_get_temp_dir(), 'cron_');
|
||||
$this->run('-l > ' . $path);
|
||||
|
||||
$jobs = [];
|
||||
$fp = \fopen(__DIR__ . '/tmpcron.tmp', 'r+');
|
||||
$fp = \fopen($path, 'r+');
|
||||
|
||||
if ($fp) {
|
||||
$line = \fgets($fp);
|
||||
|
|
@ -136,8 +140,8 @@ class Cron extends SchedulerAbstract
|
|||
\fclose($fp);
|
||||
}
|
||||
|
||||
$this->run(__DIR__ . '/tmpcron.tmp');
|
||||
\unlink(__DIR__ . '/tmpcron.tmp');
|
||||
$this->run($path);
|
||||
\unlink($path);
|
||||
|
||||
return $jobs;
|
||||
}
|
||||
|
|
@ -147,10 +151,11 @@ class Cron extends SchedulerAbstract
|
|||
*/
|
||||
public function getAllByName(string $name, bool $exact = true) : array
|
||||
{
|
||||
$this->run('-l > ' . __DIR__ . '/tmpcron.tmp');
|
||||
$path = \tempnam(\sys_get_temp_dir(), 'cron_');
|
||||
$this->run('-l > ' . $path);
|
||||
|
||||
$jobs = [];
|
||||
$fp = \fopen(__DIR__ . '/tmpcron.tmp', 'r+');
|
||||
$fp = \fopen($path, 'r+');
|
||||
|
||||
if ($fp) {
|
||||
$line = \fgets($fp);
|
||||
|
|
@ -168,8 +173,8 @@ class Cron extends SchedulerAbstract
|
|||
\fclose($fp);
|
||||
}
|
||||
|
||||
$this->run(__DIR__ . '/tmpcron.tmp');
|
||||
\unlink(__DIR__ . '/tmpcron.tmp');
|
||||
$this->run($path);
|
||||
\unlink($path);
|
||||
|
||||
return $jobs;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -355,4 +355,9 @@ class View extends ViewAbstract
|
|||
{
|
||||
return $this->l11nManager->getDateTime($this->l11n, $datetime, $format);
|
||||
}
|
||||
|
||||
public function renderUserName(string $format, array $names) : string
|
||||
{
|
||||
return \trim(\preg_replace('/\s+/', ' ', \sprintf($format, ...$names)));;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,4 +37,4 @@ final class SkewTest extends \PHPUnit\Framework\TestCase
|
|||
[1700, 900]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 29 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 144 KiB |
Loading…
Reference in New Issue
Block a user