diff --git a/Ai/Ocr/BasicOcr.php b/Ai/Ocr/BasicOcr.php index f503a37e3..29ff07f25 100644 --- a/Ai/Ocr/BasicOcr.php +++ b/Ai/Ocr/BasicOcr.php @@ -17,7 +17,7 @@ namespace phpOMS\Ai\Ocr; use phpOMS\Math\Topology\MetricsND; /** - * Matching a value with a set of coins + * Basic OCR implementation for MNIST data * * @package phpOMS\Ai\Ocr * @license OMS License 1.0 @@ -26,10 +26,38 @@ use phpOMS\Math\Topology\MetricsND; */ final class BasicOcr { + /** + * Dataset on which the OCR is trained on. + * + * The data needs to be MNIST data. + * + * @var array + * @since 1.0.0 + */ private array $Xtrain = []; + /** + * Resultset on which the OCR is trained on. + * + * These are the actual values for the Xtrain data and must therefore have the same dimension. + * + * The labels need to be MNIST labels. + * + * @var array + * @since 1.0.0 + */ private array $ytrain = []; + /** + * Train OCR with data and result/labels + * + * @param string $dataPath Impage path to read + * @param string $labelPath Label path to read + * + * @return void + * + * @since 1.0.0 + */ public function trainWith(string $dataPath, string $labelPath) : void { $Xtrain = $this->readImages($dataPath); @@ -39,12 +67,25 @@ final class BasicOcr $this->ytrain = \array_merge($this->ytrain, $this->extractFeatures($ytrain)); } + /** + * Reat image from path + * + * @param string $path Image to read + * + * @return array + * + * @since 1.0.0 + */ private function readImages(string $path) : array { $fp = \fopen($path, 'r'); - $magicNumber = \unpack('l', \fread($fp, 4))[1]; - $numberOfImages = \unpack('l', \fread($fp, 4))[1]; - $numberOfRows = \unpack('l', \fread($fp, 4))[1]; + if ($fp === false) { + throw new \Exception(); + } + + $magicNumber = \unpack('l', \fread($fp, 4))[1]; + $numberOfImages = \unpack('l', \fread($fp, 4))[1]; + $numberOfRows = \unpack('l', \fread($fp, 4))[1]; $numberOfColumns = \unpack('l', \fread($fp, 4))[1]; $images = []; @@ -68,10 +109,23 @@ final class BasicOcr return $images; } + /** + * Read labels from from path + * + * @param string $path Labels path + * + * @return array + * + * @since 1.0.0 + */ private function readLabels(string $path) : array { $fp = \fopen($path, 'r'); - $magicNumber = \unpack('l', \fread($fp, 4))[1]; + if ($fp === false) { + throw new \Exception(); + } + + $magicNumber = \unpack('l', \fread($fp, 4))[1]; $numberOfLabels = \unpack('l', \fread($fp, 4))[1]; $labels = []; @@ -83,7 +137,35 @@ final class BasicOcr return $labels; } - public function flatten(array $data) : array + /** + * Extract data and labe information from image data + * + * @param array $data Image data and label information from the images + * + * @return array + * + * @since 1.0.0 + */ + private function extractFeatures(array $data) : array + { + $features = []; + foreach ($data as $sample) { + $features[] = $this->flatten($sample); + } + + return $features; + } + + /** + * Reduce the dimension of the data and label information + * + * @param array $data Image data and labell information to flatten + * + * @return arry + * + * @sicne 1.0.0 + */ + private function flatten(array $data) : array { $flat = []; foreach ($data as $sublist) { @@ -95,16 +177,14 @@ final class BasicOcr return $flat; } - private function extractFeatures(array $data) : array - { - $features = []; - foreach ($data as $sample) { - $features[] = $this->flatten($sample); - } - - return $features; - } - + /** + * Find the k-nearest matches for test data + * + * @param array $Xtrain Image data used for training + * @param array $ytrain Labels associated with the trained data + * @param array $Xtrain Image data from the image to categorize + * @param int $k Amount of best fits that should be found + */ private function kNearest(array $Xtrain, array $ytrain, array $Xtest, int $k = 3) : array { $predictedLabels = []; @@ -114,7 +194,7 @@ final class BasicOcr \asort($distances); // find possible k-labels for a image - $kKeys = \array_keys(\array_slice($distances, 0, $k)); + $kKeys = \array_keys(\array_slice($distances, 0, $k)); $candidateLabels = []; foreach ($kKeys as $key) { @@ -131,7 +211,17 @@ final class BasicOcr return $predictedLabels; } - private function getDistances(array $Xtrain, $sample) : array + /** + * Fitting method in order to see how similar two datasets are. + * + * @param array $Xtrain Image data used for training + * @param array $sample Image data to compare against + * + * @return array + * + * @since 1.0.0 + */ + private function getDistances(array $Xtrain, array $sample) : array { $dist = []; foreach ($Xtrain as $train) { @@ -141,6 +231,15 @@ final class BasicOcr return $dist; } + /** + * Categorize an unknown image + * + * @param string $path Path to the image to categorize/evaluate/match against the training data + * + * @return array + * + * @since 1.0.0 + */ public function match(string $path) : array { // @todo: implement image reading if it isn't an mnist file diff --git a/Business/Marketing/PageRank.php b/Business/Marketing/PageRank.php index cf629918b..79a9d7877 100644 --- a/Business/Marketing/PageRank.php +++ b/Business/Marketing/PageRank.php @@ -118,7 +118,7 @@ final class PageRank for ($i = 0; $i < $iterations; ++$i) { foreach ($this->relations as $key => $relation) { - $PR = 0.0; + $PR = 0.0; foreach ($relation as $linkFrom) { $PR += $this->pageRanks[$linkFrom] / $this->outgoing[$linkFrom]; diff --git a/DataStorage/Database/DataMapperAbstract.php b/DataStorage/Database/DataMapperAbstract.php index b74e673d2..4960ccf79 100644 --- a/DataStorage/Database/DataMapperAbstract.php +++ b/DataStorage/Database/DataMapperAbstract.php @@ -837,9 +837,9 @@ class DataMapperAbstract implements DataMapperInterface $values = $obj[$propertyName] ?? null; /** @var self $mapper */ - $mapper = static::$hasMany[$propertyName]['mapper']; + $mapper = static::$hasMany[$propertyName]['mapper']; - if (\is_object($values)) { + if (\is_array($values)) { // conditionals $values[$mapper::$columns[static::$hasMany[$propertyName]['external']]['internal']] = $objId; diff --git a/System/File/FileUtils.php b/System/File/FileUtils.php index c17ac0a9c..101ecc707 100644 --- a/System/File/FileUtils.php +++ b/System/File/FileUtils.php @@ -98,7 +98,7 @@ final class FileUtils */ public static function absolute(string $origPath) : string { - if (\file_exists($origPath) || \realpath($origPath) !== false) { + if (\realpath($origPath) !== false) { return \realpath($origPath); } diff --git a/Uri/UriFactory.php b/Uri/UriFactory.php index e463cce77..e3afaf6d2 100644 --- a/Uri/UriFactory.php +++ b/Uri/UriFactory.php @@ -200,14 +200,21 @@ final class UriFactory ); $urlStructure = \parse_url($url); - \parse_str($urlStructure['query'] ?? '', $urlStructure['query']); + + if ($urlStructure === false) { + return $url; + } + + if (isset($urlStructure['query'])) { + \parse_str($urlStructure['query'] ?? '', $urlStructure['query']); + } $escaped = (isset($urlStructure['scheme']) && !empty($urlStructure['scheme']) ? $urlStructure['scheme'] . '://' : '') - . (isset($urlStructure['username']) && !empty($urlStructure['username']) + . (isset($urlStructure['username']) ? $urlStructure['username'] . ':' : '') - . (isset($urlStructure['password']) && !empty($urlStructure['password']) + . (isset($urlStructure['password']) ? $urlStructure['password'] . '@' : '') . (isset($urlStructure['host']) && !empty($urlStructure['host']) ? $urlStructure['host'] : '')