From 21bef410ff64348165ae13c6c7ae43c0af76bba9 Mon Sep 17 00:00:00 2001 From: HokutoTateyama Date: Sat, 10 Aug 2019 19:14:26 +0900 Subject: [PATCH 01/21] First commit with base codes --- .github/ISSUE_TEMPLATE.md | 0 .github/PULL_REQUEST_TEMPLATE.md | 0 .gitignore | 6 ++ .travis.yml | 17 +++++ LICENSE | 27 ++++++++ MANIFEST.in | 0 README.md | 2 + ife/__init__.py | 12 ++++ ife/data/__init__.py | 0 ife/data/small_rgb.jpg | Bin 0 -> 129 bytes ife/data/strawberry.jpg | Bin 0 -> 3067 bytes ife/features/__init__.py | 3 + ife/features/features.py | 49 +++++++++++++++ ife/features/moment.py | 40 ++++++++++++ ife/features/tests/__init__.py | 0 ife/features/tests/test_features.py | 28 +++++++++ ife/features/tests/test_moment.py | 18 ++++++ ife/io/__init__.py | 0 ife/io/io.py | 23 +++++++ ife/io/tests/__init__.py | 0 ife/io/tests/test_io.py | 19 ++++++ ife/util/__init__.py | 0 ife/util/array.py | 28 +++++++++ ife/util/tests/__init__.py | 0 ife/util/tests/test_array.py | 55 +++++++++++++++++ poetry.lock | 92 ++++++++++++++++++++++++++++ pyproject.toml | 30 +++++++++ usage.py | 11 ++++ 28 files changed, 460 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 LICENSE create mode 100644 MANIFEST.in create mode 100644 ife/__init__.py create mode 100644 ife/data/__init__.py create mode 100644 ife/data/small_rgb.jpg create mode 100644 ife/data/strawberry.jpg create mode 100644 ife/features/__init__.py create mode 100644 ife/features/features.py create mode 100644 ife/features/moment.py create mode 100644 ife/features/tests/__init__.py create mode 100644 ife/features/tests/test_features.py create mode 100644 ife/features/tests/test_moment.py create mode 100644 ife/io/__init__.py create mode 100644 ife/io/io.py create mode 100644 ife/io/tests/__init__.py create mode 100644 ife/io/tests/test_io.py create mode 100644 ife/util/__init__.py create mode 100644 ife/util/array.py create mode 100644 ife/util/tests/__init__.py create mode 100644 ife/util/tests/test_array.py create mode 100644 poetry.lock create mode 100644 pyproject.toml create mode 100644 usage.py diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..e69de29 diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..e69de29 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4e3b816 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +#Python byte code +__pycache__/ +*.py[cod] + +# PyCharm +.idea/ diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..aa0ad0a --- /dev/null +++ b/.travis.yml @@ -0,0 +1,17 @@ +language: python +python: + - "3.5" + - "3.5-dev" # 3.5 development branch + - "3.6" + - "3.6-dev" # 3.6 development branch +branches: + only: + - master + - develop +# command to install dependencies +install: + - pip install coveralls +script: + - python -m unittest discover -v +after_success: + - coveralls \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..31f70ca --- /dev/null +++ b/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2019, Collonville. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the name of Collonville nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE \ No newline at end of file diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..e69de29 diff --git a/README.md b/README.md index f8e8103..f6e43ca 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,4 @@ +[![Coverage Status](https://coveralls.io/repos/github/Collonville/ImageFeatureExtractor/badge.svg?branch=master)](https://coveralls.io/github/Collonville/ImageFeatureExtractor?branch=master) + # ImageFeatureExtractor Want a great image features??? Use IFE package!!! diff --git a/ife/__init__.py b/ife/__init__.py new file mode 100644 index 0000000..4999179 --- /dev/null +++ b/ife/__init__.py @@ -0,0 +1,12 @@ +from ife.io.io import ImageReader +from ife.features.features import Features + +__copyright__ = "Copyright (C) 2019 Collonville" +__version__ = "0.1.0" +__license__ = "BSD-3-Clause" +__author__ = "Collonville" +__author_email__ = "ht235711@yahoo.co.jp" +__url__ = "" + +__all__ = [ImageReader] +__all__ += [Features] diff --git a/ife/data/__init__.py b/ife/data/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ife/data/small_rgb.jpg b/ife/data/small_rgb.jpg new file mode 100644 index 0000000000000000000000000000000000000000..69085624ff9fc887c09e28d816d7bf1526e2cca2 GIT binary patch literal 129 zcmeAS@N?(olHy`uVBq!ia0vp^Od!kwBL7~QRScvUi-X*q7}lMWc?smOq&xaLGB9lH z=l+w(3gmMZctipf@f`+X#^d=bQh|Nm!HdBZk0 T<%`4}pb7?0S3j3^P6ZaWG!oG$i9)!kMe!s8p^Ljnc^Zh>W=V44TJ_9`0^pW}i2m}It zXD)z21g!M}uucGgLIE-W0I&lrpkn}-X@Qsvh{6JppEdwUF>e3>KLh>S`;6r;FW1mB z@Lx9U_0LFvu@1=o=HlV&;p5`rDW)uc4$#m=q9Bq#y*y(gaZ`_hYRJkxj*KDZ$5Gf3?xTnH;UkCX zhgrcv+8$E9$TvH?fCGc%4wXpY)s^u3Oc~XF5zpDBtuB z=iuZ&DIj=CQcC*FSs4{oHFb^i7cO7X(>J(^ymsBp+yZTBW$kdw(aG5b>+0j{ch^54 zFeu_dbnMgk z#N^a8kwpHou(-6mvP#?B+Wz)^hravckc&Cbe_{Pi_8(llOfDAY3?R@$E)a`9^MH9F ztm2An$8=1f_Fl&&li&`o+?)yV-@Hl_02^d9EqN2m}bX@_V($^JXA@c)bKZ?J!J zO#|Fu5Oa87UO*ezHl7jsK2Eh;N7Bl>q`R95F`B1eVgg)ekEjjEQZZnEC0@2ktNz;I zauv*N_FlAD#_sM8x%9^Mo}JR?0a&+h``1Xftv0NKv!3QRCrde@GeQbnZ^=fQoXh&e zSJkkrFeCjvkgC~1HR+gYF`{O)(?f$DC3m8~ojz$ZD_Qrf$ zOW}cEwqu?do*SjVxKxyUgLRk^u%#O?d6WA0qW>qFXS< zlIA#-wRTD?GOKd!)$l^$lQNNF_Gq`hREvPvenS=&O$XYb0ezQ7c^xJ|vxx9w0Gt!X z4P)fys;ZcDQ!B?)~qx0@XSJQ34#SqR!14F3_5D>EcZFr?eRaJ9G~)AOAjo>*7A^Ri_G`(@_T=U)n| z-k?)t-MjJ?OlT*`2kDNa+rf{c;-&Bf%bxKTTV{=!Ht&%YmIn)(ixE;tM6&6?uCd~+ zxOJb+jS#-!1Id6qBEI@DH(_e!yQ^I5zTt08wJ2R;y6;QzSo7aY@ADi3MMj@ts7xAM+ne~dr8PUc zCs;tyQVo9LOGov@-TYLcH2{f{YkZ+GcfZa^>Ex0v+xeL<+9w%+v!U^kJ^j%=dk>Me zg~j5uptB91D&~A=5HO!b+qb-y1xmK|V~c7$?^3xTkJc^Pg-5ox69UAm5>T9dq;S)4 z@8wS5Jck7ARHV-!MW7uVu>*;_fO?`yBN za&+fN&q$8U>IwruYo(b>vu}2;NIEZ81_vk-p+vmC|9%$Fuvzvu*1ycU;xm*ITCGDN66Lrrp<` z+{z5Wt5)_1w7G?*#k=Q>B9{Yj>r*s?t^*!XyRNMFLKO9;bfcz+!&mMOck)Fx)`bf> z;VwvV2=^5DqIG;u@!uid#&ycI8j=+R1HiUpQq9Tp<0vb+?d`<8`3o~8*`J*?#NMcj z78z?=Ogzv;64QqKxa?xBLz?sAv2cts?A*iX7Q_Nt(9Z+A z|456KZcIw=ylA;6R5mwBX%^XEol`^iCOi1a#`c!6^$xh-Q@H49R&TbXbpkJJfxVt7 zTqjXy{k4X$H#n)$Aw96EB~Wm$tUyyGJ5c8Bc&59b8NPW0EA_)~Y~30rQqJ3O7iJ=} zrFU1FNa(S-ydaB}c()1VT?*3}G}=b5W+!iH!xk|H!zU$#6d)g8%_6zoxdauryuA{T z(8`?zXbIndW&HIXs%k|VUNz2ygxs+22Bl-gloe-gKUiJ-5ak#@t8xZE7=zw<(fpU&Yj7mj;}Yg*gx|LouMudY%t? zwBzqEXXyLXl&&8J55CR8Zcx`38&&N1YQ6hPDiRa)DYaX|QKk>Vt7_x8#O=;)aP=~P zPFu~(WmxO5r{oW!BD$l7o00f$FUv)jzd!_T9XpGF1BKgM65TrQtF!W6CFBJX2dB#4 z&|H%-n7JD^edR)i_5PcumhMzbxWgg$5bvC1^+yJb`$pfdk`y!Iq~sc)WfN|p6GF=^ zR)P49!P>WuliX6MhaWugMt(wZDN|ZDNYzl%+UTh7y0bIQZjX=BSx}U0 z3_QG&pi2=n9jp~IE!N*a-ECfqD5y?Qj|)tC1-j*8B0%=C-&~)aLVWo`RZL(Fw$ewV z6=Jgsi!Qp(%>;c5ZrQ<6jTMwgt{HokuvD`SIiZcOxP{RYnY&vm`E&{?!@>NZkGe2E z1kG-Kd9?;t%a`ssXe+88nBT;qf-OlZR1d<=`-f1(-9tl{D~k`tHV@j#eQM$V&Go|mA~_g7u=Ti4`!H}FkEd;WS) zeV3;$!&Rcq;=wV)TOe)DHV8Wo0MFoTxjOH4PZ`3wP*&Wuq%>d*F Z$TU%N)mkT~{pnEho{EWHV2KW6>YqB%m$3i< literal 0 HcmV?d00001 diff --git a/ife/features/__init__.py b/ife/features/__init__.py new file mode 100644 index 0000000..ae5ed49 --- /dev/null +++ b/ife/features/__init__.py @@ -0,0 +1,3 @@ +from .features import moment + +__all__ = ["moment"] diff --git a/ife/features/features.py b/ife/features/features.py new file mode 100644 index 0000000..ef07e84 --- /dev/null +++ b/ife/features/features.py @@ -0,0 +1,49 @@ +from collections import defaultdict + +import numpy as np +import pandas as pd + +from typing import Optional, Union + +from ife.util.array import to_2d_array, convert_color_space_from_rgb +from . import moment + + +class Features: + np_image: np.ndarray + + def __init__(self, np_image): + self.np_image = np_image + + def moment( + self, + required_methods: Optional[Union[str, list]] = None, + color_space: Optional[str] = "RGB", + output_type: Optional[str] = None, + ): + np_2d_image = convert_color_space_from_rgb( + to_2d_array(self.np_image), color_space + ) + + method_list = moment.get_method(required_methods) + + moment_value = np.array([method(np_2d_image) for method in method_list]) + + if output_type is None or output_type is "": + return moment_value + elif output_type == "one_col": + return moment_value.flatten() + + dict_result = defaultdict(dict) + for method_idx, method in enumerate(method_list): + for index in range(moment_value.shape[1]): + dict_result[method.__name__][color_space[index]] = moment_value[ + method_idx, index + ] + + if output_type == "dict": + return dict_result + elif output_type == "pandas": + return pd.DataFrame(dict_result) + else: + raise ValueError("Undefined output type.") diff --git a/ife/features/moment.py b/ife/features/moment.py new file mode 100644 index 0000000..e8c40f7 --- /dev/null +++ b/ife/features/moment.py @@ -0,0 +1,40 @@ +from typing import Optional, Union + +import numpy as np +from scipy import stats + + +def get_method(method: Optional[Union[str, list]] = None): + if method is None: + return MOMENT_METHODS.values() + else: + return [MOMENT_METHODS[method_name] for method_name in [method]] + + +def mean(np_2d_image: np.ndarray): + return np.mean(np_2d_image, axis=0) + + +def median(np_2d_image: np.ndarray): + return np.median(np_2d_image, axis=0) + + +def var(np_2d_image: np.ndarray): + return np.var(np_2d_image, axis=0) + + +def skew(np_2d_image: np.ndarray): + return stats.skew(np_2d_image, axis=0) + + +def kurtosis(np_2d_image: np.ndarray): + return stats.kurtosis(np_2d_image, axis=0) + + +MOMENT_METHODS = { + "Mean": mean, + "Median": median, + "Var": var, + "Skew": skew, + "kurtosis": kurtosis, +} diff --git a/ife/features/tests/__init__.py b/ife/features/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ife/features/tests/test_features.py b/ife/features/tests/test_features.py new file mode 100644 index 0000000..021d24e --- /dev/null +++ b/ife/features/tests/test_features.py @@ -0,0 +1,28 @@ +import unittest +from collections import defaultdict + +import numpy as np +import pandas as pd + +from ife.io.io import ImageReader + + +class TestMomentFeatures(unittest.TestCase): + def test_output_type(self): + features = ImageReader.read_from_single_file("ife/data/small_rgb.jpg") + + moment = features.moment() + self.assertIs(np.ndarray, type(moment)) + + moment = features.moment(output_type="") + self.assertIs(np.ndarray, type(moment)) + + moment = features.moment(output_type="one_col") + self.assertIs(np.ndarray, type(moment)) + self.assertEqual(np.zeros(15).shape, moment.shape) + + moment = features.moment(output_type="dict") + self.assertIs(defaultdict, type(moment)) + + moment = features.moment(output_type="pandas") + self.assertIs(pd.DataFrame, type(moment)) diff --git a/ife/features/tests/test_moment.py b/ife/features/tests/test_moment.py new file mode 100644 index 0000000..22d37bf --- /dev/null +++ b/ife/features/tests/test_moment.py @@ -0,0 +1,18 @@ +import unittest + + +class TestMoment(unittest.TestCase): + def test_mean(self): + pass + + def test_median(self): + pass + + def test_var(self): + pass + + def test_skew(self): + pass + + def test_kurtosis(self): + pass diff --git a/ife/io/__init__.py b/ife/io/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ife/io/io.py b/ife/io/io.py new file mode 100644 index 0000000..79613c5 --- /dev/null +++ b/ife/io/io.py @@ -0,0 +1,23 @@ +import os + +import numpy as np +from PIL import Image + +from ife.features.features import Features + + +class ImageReader: + def __init__(self): + None + + @classmethod + def read_from_single_file(cls, file_path: str) -> Features: + if not isinstance(file_path, str): + raise ValueError("Set string or list file path.") + + if not os.path.exists(file_path): + raise FileExistsError("File {} does not exist.".format(file_path)) + + np_image = np.array(Image.open(file_path).convert("RGB")) / 255.0 + + return Features(np_image) diff --git a/ife/io/tests/__init__.py b/ife/io/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ife/io/tests/test_io.py b/ife/io/tests/test_io.py new file mode 100644 index 0000000..db1f11d --- /dev/null +++ b/ife/io/tests/test_io.py @@ -0,0 +1,19 @@ +import unittest + +from ife.io.io import ImageReader, Features + + +class TestIO(unittest.TestCase): + def test_undefined_type(self): + with self.assertRaises(ValueError): + ImageReader().read_from_single_file(["", ""]) + + def test_unreachable_file(self): + with self.assertRaises(FileExistsError): + ImageReader().read_from_single_file("../../data/none") + + def test_reachable_file(self): + expected = Features + actual = ImageReader().read_from_single_file("ife/data/small_rgb.jpg") + + self.assertIs(expected, type(actual)) diff --git a/ife/util/__init__.py b/ife/util/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ife/util/array.py b/ife/util/array.py new file mode 100644 index 0000000..60e1c59 --- /dev/null +++ b/ife/util/array.py @@ -0,0 +1,28 @@ +import colour +import numpy as np + + +def to_2d_array(array: np.ndarray): + dimension = len(array.shape) + + if dimension == 1: + raise ValueError("Array dimension is 1. Set array more than 2 dimension.") + elif dimension == 2: + return array + + return array.reshape((array.shape[0] * array.shape[1], array.shape[-1])) + + +def convert_color_space_from_rgb( + np_image: np.ndarray, dest_color_space: str +) -> np.ndarray: + if dest_color_space == "RGB": + return np_image + elif dest_color_space == "HSV": + return colour.RGB_to_HSV(np_image) + elif dest_color_space == "HSL": + return colour.RGB_to_HSL(np_image) + elif dest_color_space == "CMY": + return colour.RGB_to_CMY(np_image) + else: + raise ValueError("Undefined color space.") diff --git a/ife/util/tests/__init__.py b/ife/util/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ife/util/tests/test_array.py b/ife/util/tests/test_array.py new file mode 100644 index 0000000..01aa145 --- /dev/null +++ b/ife/util/tests/test_array.py @@ -0,0 +1,55 @@ +import unittest + +import numpy as np +from colour.utilities import filter_warnings + +from ife.util.array import to_2d_array, convert_color_space_from_rgb + + +class Test2dArray(unittest.TestCase): + def test_1dim(self): + with self.assertRaises(ValueError): + to_2d_array(np.arange(4.0)) + + def test_2dim(self): + expected = np.array([[0, 1, 2], [3, 4, 5]], np.float) + actual = to_2d_array(np.arange(6.0).reshape(2, 3)) + + np.testing.assert_array_equal(expected, actual) + + def test_3dim(self): + expected = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]], np.float) + actual = to_2d_array(np.arange(12.0).reshape(2, 2, 3)) + + np.testing.assert_array_equal(expected, actual) + + +class TestColorConvertFromRGB(unittest.TestCase): + def test_rgb_2_rgb(self): + expected = np.array([0, 0, 0]) + actual = convert_color_space_from_rgb(np.array([0, 0, 0]), "RGB") + + np.testing.assert_array_equal(expected, actual) + + expected = np.array([0.2, 0.4, 0.8]) + actual = convert_color_space_from_rgb(np.array([0.2, 0.4, 0.8]), "RGB") + + np.testing.assert_array_equal(expected, actual) + + def test_rgb_2_hsv(self): + filter_warnings(python_warnings=True) + expected = np.array([0, 0, 0]) + actual = convert_color_space_from_rgb(np.array([0, 0, 0]), "HSV") + + np.testing.assert_array_almost_equal(expected, actual) + + expected = np.array([0.611, 0.75, 0.80]) + actual = convert_color_space_from_rgb(np.array([0.2, 0.4, 0.8]), "HSV") + + np.testing.assert_array_almost_equal(expected, actual, decimal=3) + + def test_rgb_2_hsl(self): + pass + + def test_rgb_2_cmy(self): + pass diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 0000000..65b5905 --- /dev/null +++ b/poetry.lock @@ -0,0 +1,92 @@ +[[package]] +category = "main" +description = "Colour Science for Python" +name = "colour-science" +optional = false +python-versions = "*" +version = "0.3.13" + +[package.dependencies] +scipy = ">=0.16.0" +six = ">=1.10.0" + +[[package]] +category = "main" +description = "NumPy is the fundamental package for array computing with Python." +name = "numpy" +optional = false +python-versions = ">=3.5" +version = "1.17.0" + +[[package]] +category = "main" +description = "Powerful data structures for data analysis, time series, and statistics" +name = "pandas" +optional = false +python-versions = ">=3.5.3" +version = "0.25.0" + +[package.dependencies] +numpy = ">=1.13.3" +python-dateutil = ">=2.6.1" +pytz = ">=2017.2" + +[[package]] +category = "main" +description = "Python Imaging Library (Fork)" +name = "pillow" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "6.1.0" + +[[package]] +category = "main" +description = "Extensions to the standard Python datetime module" +name = "python-dateutil" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +version = "2.8.0" + +[package.dependencies] +six = ">=1.5" + +[[package]] +category = "main" +description = "World timezone definitions, modern and historical" +name = "pytz" +optional = false +python-versions = "*" +version = "2019.2" + +[[package]] +category = "main" +description = "SciPy: Scientific Library for Python" +name = "scipy" +optional = false +python-versions = ">=3.5" +version = "1.3.1" + +[package.dependencies] +numpy = ">=1.13.3" + +[[package]] +category = "main" +description = "Python 2 and 3 compatibility utilities" +name = "six" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*" +version = "1.12.0" + +[metadata] +content-hash = "81b6833e373b7dbb66bd7f09af14561d5de0cf608032895171f512748e284faf" +python-versions = "^3.6" + +[metadata.hashes] +colour-science = ["4f03919b96a055c08b4cd174878224ae89680f721e13d0cefe98ce026491bc2d", "5f6b25a3bdd2d5fa7bca81a1b8b1a1418cff5d238622c86449dc6b52cd2819fa"] +numpy = ["03e311b0a4c9f5755da7d52161280c6a78406c7be5c5cc7facfbcebb641efb7e", "0cdd229a53d2720d21175012ab0599665f8c9588b3b8ffa6095dd7b90f0691dd", "312bb18e95218bedc3563f26fcc9c1c6bfaaf9d453d15942c0839acdd7e4c473", "464b1c48baf49e8505b1bb754c47a013d2c305c5b14269b5c85ea0625b6a988a", "5adfde7bd3ee4864536e230bcab1c673f866736698724d5d28c11a4d63672658", "7724e9e31ee72389d522b88c0d4201f24edc34277999701ccd4a5392e7d8af61", "8d36f7c53ae741e23f54793ffefb2912340b800476eb0a831c6eb602e204c5c4", "910d2272403c2ea8a52d9159827dc9f7c27fb4b263749dca884e2e4a8af3b302", "951fefe2fb73f84c620bec4e001e80a80ddaa1b84dce244ded7f1e0cbe0ed34a", "9588c6b4157f493edeb9378788dcd02cb9e6a6aeaa518b511a1c79d06cbd8094", "9ce8300950f2f1d29d0e49c28ebfff0d2f1e2a7444830fbb0b913c7c08f31511", "be39cca66cc6806652da97103605c7b65ee4442c638f04ff064a7efd9a81d50a", "c3ab2d835b95ccb59d11dfcd56eb0480daea57cdf95d686d22eff35584bc4554", "eb0fc4a492cb896346c9e2c7a22eae3e766d407df3eb20f4ce027f23f76e4c54", "ec0c56eae6cee6299f41e780a0280318a93db519bbb2906103c43f3e2be1206c", "f4e4612de60a4f1c4d06c8c2857cdcb2b8b5289189a12053f37d3f41f06c60d0"] +pandas = ["074a032f99bb55d178b93bd98999c971542f19317829af08c99504febd9e9b8b", "20f1728182b49575c2f6f681b3e2af5fac9e84abdf29488e76d569a7969b362e", "2745ba6e16c34d13d765c3657bb64fa20a0e2daf503e6216a36ed61770066179", "32c44e5b628c48ba17703f734d59f369d4cdcb4239ef26047d6c8a8bfda29a6b", "3b9f7dcee6744d9dcdd53bce19b91d20b4311bf904303fa00ef58e7df398e901", "544f2033250980fb6f069ce4a960e5f64d99b8165d01dc39afd0b244eeeef7d7", "58f9ef68975b9f00ba96755d5702afdf039dea9acef6a0cfd8ddcde32918a79c", "9023972a92073a495eba1380824b197ad1737550fe1c4ef8322e65fe58662888", "914341ad2d5b1ea522798efa4016430b66107d05781dbfe7cf05eba8f37df995", "9d151bfb0e751e2c987f931c57792871c8d7ff292bcdfcaa7233012c367940ee", "b932b127da810fef57d427260dde1ad54542c136c44b227a1e367551bb1a684b", "cfb862aa37f4dd5be0730731fdb8185ac935aba8b51bf3bd035658111c9ee1c9", "de7ecb4b120e98b91e8a2a21f186571266a8d1faa31d92421e979c7ca67d8e5c", "df7e1933a0b83920769611c5d6b9a1bf301e3fa6a544641c6678c67621fe9843"] +pillow = ["0804f77cb1e9b6dbd37601cee11283bba39a8d44b9ddb053400c58e0c0d7d9de", "0ab7c5b5d04691bcbd570658667dd1e21ca311c62dcfd315ad2255b1cd37f64f", "0b3e6cf3ea1f8cecd625f1420b931c83ce74f00c29a0ff1ce4385f99900ac7c4", "0c6ce6ae03a50b0306a683696234b8bc88c5b292d4181ae365b89bd90250ab08", "1454ee7297a81c8308ad61d74c849486efa1badc543453c4b90db0bf99decc1c", "23efd7f83f2ad6036e2b9ef27a46df7e333de1ad9087d341d87e12225d0142b2", "365c06a45712cd723ec16fa4ceb32ce46ad201eb7bbf6d3c16b063c72b61a3ed", "38301fbc0af865baa4752ddae1bb3cbb24b3d8f221bf2850aad96b243306fa03", "3aef1af1a91798536bbab35d70d35750bd2884f0832c88aeb2499aa2d1ed4992", "3c86051d41d1c8b28b9dde08ac93e73aa842991995b12771b0af28da49086bbf", "3fe0ab49537d9330c9bba7f16a5f8b02da615b5c809cdf7124f356a0f182eccd", "406c856e0f6fc330322a319457d9ff6162834050cda2cf1eaaaea4b771d01914", "45a619d5c1915957449264c81c008934452e3fd3604e36809212300b2a4dab68", "49f90f147883a0c3778fd29d3eb169d56416f25758d0f66775db9184debc8010", "504f5334bfd974490a86fef3e3b494cd3c332a8a680d2f258ca03388b40ae230", "51fe9cfcd32c849c6f36ca293648f279fc5097ca8dd6e518b10df3a6a9a13431", "571b5a758baf1cb6a04233fb23d6cf1ca60b31f9f641b1700bfaab1194020555", "5ac381e8b1259925287ccc5a87d9cf6322a2dc88ae28a97fe3e196385288413f", "6052a9e9af4a9a2cc01da4bbee81d42d33feca2bde247c4916d8274b12bb31a4", "6153db744a743c0c8c91b8e3b9d40e0b13a5d31dbf8a12748c6d9bfd3ddc01ad", "6fd63afd14a16f5d6b408f623cc2142917a1f92855f0df997e09a49f0341be8a", "70acbcaba2a638923c2d337e0edea210505708d7859b87c2bd81e8f9902ae826", "70b1594d56ed32d56ed21a7fbb2a5c6fd7446cdb7b21e749c9791eac3a64d9e4", "76638865c83b1bb33bcac2a61ce4d13c17dba2204969dedb9ab60ef62bede686", "7b2ec162c87fc496aa568258ac88631a2ce0acfe681a9af40842fc55deaedc99", "7b403ea842b70c4fa0a4969a5d8d86e932c941095b7cda077ea68f7b98ead30b", "7be698a28175eae5354da94f5f3dc787d5efae6aca7ad1f286a781afde6a27dd", "7cee2cef07c8d76894ebefc54e4bb707dfc7f258ad155bd61d87f6cd487a70ff", "7d16d4498f8b374fc625c4037742fbdd7f9ac383fd50b06f4df00c81ef60e829", "82840783842b27933cc6388800cb547f31caf436f7e23384d456bdf5fc8dfe49", "8755e600b33f4e8c76a590b42acc35d24f4dc801a5868519ce569b9462d77598", "9159285ab4030c6f85e001468cb5886de05e6bd9304e9e7d46b983f7d2fad0cc", "b50bc1780681b127e28f0075dfb81d6135c3a293e0c1d0211133c75e2179b6c0", "b5aa19f1da16b4f5e47b6930053f08cba77ceccaed68748061b0ec24860e510c", "bd0582f831ad5bcad6ca001deba4568573a4675437db17c4031939156ff339fa", "cdd53acd3afb9878a2289a1b55807871f9877c81174ae0d3763e52f907131d25", "cfd40d8a4b59f7567620410f966bb1f32dc555b2b19f82a91b147fac296f645c", "e150c5aed6e67321edc6893faa6701581ca2d393472f39142a00e551bcd249a5", "e3ae410089de680e8f84c68b755b42bc42c0ceb8c03dbea88a5099747091d38e", "e403b37c6a253ebca5d0f2e5624643997aaae529dc96299162418ef54e29eb70", "e9046e559c299b395b39ac7dbf16005308821c2f24a63cae2ab173bd6aa11616", "ef6be704ae2bc8ad0ebc5cb850ee9139493b0fc4e81abcc240fb392a63ebc808", "f8dc19d92896558f9c4317ee365729ead9d7bbcf2052a9a19a3ef17abbb8ac5b"] +python-dateutil = ["7e6584c74aeed623791615e26efd690f29817a27c73085b78e4bad02493df2fb", "c89805f6f4d64db21ed966fda138f8a5ed7a4fdbc1a8ee329ce1b74e3c74da9e"] +pytz = ["26c0b32e437e54a18161324a2fca3c4b9846b74a8dccddd843113109e1116b32", "c894d57500a4cd2d5c71114aaab77dbab5eabd9022308ce5ac9bb93a60a6f0c7"] +scipy = ["0baa64bf42592032f6f6445a07144e355ca876b177f47ad8d0612901c9375bef", "243b04730d7223d2b844bda9500310eecc9eda0cba9ceaf0cde1839f8287dfa8", "2643cfb46d97b7797d1dbdb6f3c23fe3402904e3c90e6facfe6a9b98d808c1b5", "396eb4cdad421f846a1498299474f0a3752921229388f91f60dc3eda55a00488", "3ae3692616975d3c10aca6d574d6b4ff95568768d4525f76222fb60f142075b9", "435d19f80b4dcf67dc090cc04fde2c5c8a70b3372e64f6a9c58c5b806abfa5a8", "46a5e55850cfe02332998b3aef481d33f1efee1960fe6cfee0202c7dd6fc21ab", "75b513c462e58eeca82b22fc00f0d1875a37b12913eee9d979233349fce5c8b2", "7ccfa44a08226825126c4ef0027aa46a38c928a10f0a8a8483c80dd9f9a0ad44", "89dd6a6d329e3f693d1204d5562dd63af0fd7a17854ced17f9cbc37d5b853c8d", "a81da2fe32f4eab8b60d56ad43e44d93d392da228a77e229e59b51508a00299c", "a9d606d11eb2eec7ef893eb825017fbb6eef1e1d0b98a5b7fc11446ebeb2b9b1", "ac37eb652248e2d7cbbfd89619dce5ecfd27d657e714ed049d82f19b162e8d45", "cbc0611699e420774e945f6a4e2830f7ca2b3ee3483fca1aa659100049487dd5", "d02d813ec9958ed63b390ded463163685af6025cb2e9a226ec2c477df90c6957", "dd3b52e00f93fd1c86f2d78243dfb0d02743c94dd1d34ffea10055438e63b99d"] +six = ["3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", "d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"] diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..42b6cfc --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,30 @@ +[tool.poetry] +name = "imagefeatureextractor" +version = "0.1.0" +description = "You can get a nice global image feature!!" +authors = ["HokutoTateyama "] +repository = "https://github.com/Collonville/ImageFeatureExtractor" +license = "BSD-3-Clause" +readme = "README.md" +classifiers =[ + "Development Status :: 2 - Pre-Alpha", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Topic :: Scientific/Engineering" +] + +[tool.poetry.dependencies] +python = "^3.6" +Pillow = "^6.1" +colour-science = "^0.3.13" +pandas = "^0.25.0" + +[tool.poetry.dev-dependencies] +python = "^3.6" +Pillow = "^6.1" +colour-science = "^0.3.13" +pandas = "^0.25.0" + +[build-system] +requires = ["poetry>=0.12"] +build-backend = "poetry.masonry.api" diff --git a/usage.py b/usage.py new file mode 100644 index 0000000..c8f067b --- /dev/null +++ b/usage.py @@ -0,0 +1,11 @@ +from ife.io.io import ImageReader + + +def main(): + features = ImageReader.read_from_single_file("ife/data/small_rgb.jpg") + + print(features.moment(output_type="pandas")) + + +if __name__ == "__main__": + main() From 1bd66959d4c3853ab176992f50920094b847c9df Mon Sep 17 00:00:00 2001 From: HokutoTateyama Date: Sat, 10 Aug 2019 19:27:18 +0900 Subject: [PATCH 02/21] Add poetry install --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index aa0ad0a..91e76d7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,11 @@ branches: - master - develop # command to install dependencies +before_install: + - pip install --upgrade pip + - pip install poetry install: + - poetry install -v - pip install coveralls script: - python -m unittest discover -v From 24aedc692a9c6c2bb2f5d62febe920ecdf1de866 Mon Sep 17 00:00:00 2001 From: HokutoTateyama Date: Sat, 10 Aug 2019 20:28:26 +0900 Subject: [PATCH 03/21] Update packages --- .travis.yml | 2 -- pyproject.toml | 4 ---- 2 files changed, 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 91e76d7..c5fbfe7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,5 @@ language: python python: - - "3.5" - - "3.5-dev" # 3.5 development branch - "3.6" - "3.6-dev" # 3.6 development branch branches: diff --git a/pyproject.toml b/pyproject.toml index 42b6cfc..a33d416 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,10 +20,6 @@ colour-science = "^0.3.13" pandas = "^0.25.0" [tool.poetry.dev-dependencies] -python = "^3.6" -Pillow = "^6.1" -colour-science = "^0.3.13" -pandas = "^0.25.0" [build-system] requires = ["poetry>=0.12"] From abac72db31e2df56501f371b3de75dbfdc5c2d4f Mon Sep 17 00:00:00 2001 From: HokutoTateyama Date: Sat, 10 Aug 2019 21:39:49 +0900 Subject: [PATCH 04/21] Code organize --- ife/__init__.py | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/ife/__init__.py b/ife/__init__.py index 4999179..e69de29 100644 --- a/ife/__init__.py +++ b/ife/__init__.py @@ -1,12 +0,0 @@ -from ife.io.io import ImageReader -from ife.features.features import Features - -__copyright__ = "Copyright (C) 2019 Collonville" -__version__ = "0.1.0" -__license__ = "BSD-3-Clause" -__author__ = "Collonville" -__author_email__ = "ht235711@yahoo.co.jp" -__url__ = "" - -__all__ = [ImageReader] -__all__ += [Features] From 862897645872e247c34ad5eb239e3919672e1c2b Mon Sep 17 00:00:00 2001 From: HokutoTateyama Date: Sat, 10 Aug 2019 21:39:58 +0900 Subject: [PATCH 05/21] Code organize --- README.md | 4 +++- ife/io/io.py | 3 --- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index f6e43ca..cda9325 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ -[![Coverage Status](https://coveralls.io/repos/github/Collonville/ImageFeatureExtractor/badge.svg?branch=master)](https://coveralls.io/github/Collonville/ImageFeatureExtractor?branch=master) +[![Coverage Status](https://coveralls.io/repos/github/Collonville/ImageFeatureExtractor/badge.svg)](https://coveralls.io/github/Collonville/ImageFeatureExtractor) +[![Build Status](https://travis-ci.org/Collonville/ImageFeatureExtractor.svg?branch=develop)](https://travis-ci.org/Collonville/ImageFeatureExtractor) +[![Codacy Badge](https://api.codacy.com/project/badge/Grade/115c65043153459cbfc5026ea53be08d)](https://www.codacy.com/app/Collonville/ImageFeatureExtractor?utm_source=github.com&utm_medium=referral&utm_content=Collonville/ImageFeatureExtractor&utm_campaign=Badge_Grade) # ImageFeatureExtractor Want a great image features??? Use IFE package!!! diff --git a/ife/io/io.py b/ife/io/io.py index 79613c5..8fcf0a0 100644 --- a/ife/io/io.py +++ b/ife/io/io.py @@ -7,9 +7,6 @@ class ImageReader: - def __init__(self): - None - @classmethod def read_from_single_file(cls, file_path: str) -> Features: if not isinstance(file_path, str): From 7b896436f6326ad4e84c6b6829e32ca2ad1eb740 Mon Sep 17 00:00:00 2001 From: HokutoTateyama Date: Sat, 10 Aug 2019 22:15:27 +0900 Subject: [PATCH 06/21] Fix coverage do not work --- .gitignore | 2 ++ .travis.yml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 4e3b816..bfa62d4 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ __pycache__/ # PyCharm .idea/ + +.coverage \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index c5fbfe7..b1d5fe9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,6 +14,6 @@ install: - poetry install -v - pip install coveralls script: - - python -m unittest discover -v + - coverage run -m unittest discover after_success: - coveralls \ No newline at end of file From ab29b9a46ed0c89076dc4195ec6b2f6e319d4189 Mon Sep 17 00:00:00 2001 From: HokutoTateyama Date: Sat, 10 Aug 2019 23:59:52 +0900 Subject: [PATCH 07/21] Add coveragerc --- .coveragerc | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .coveragerc diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 0000000..a5436ee --- /dev/null +++ b/.coveragerc @@ -0,0 +1,2 @@ +[run] +source = ImageFeatureExtractor \ No newline at end of file From 734698eac1a60d55b056364be1340b546c5fc4f7 Mon Sep 17 00:00:00 2001 From: HokutoTateyama Date: Sun, 11 Aug 2019 00:23:54 +0900 Subject: [PATCH 08/21] Fix coveragerc --- .coveragerc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.coveragerc b/.coveragerc index a5436ee..d492764 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,2 +1,2 @@ [run] -source = ImageFeatureExtractor \ No newline at end of file +source = ife \ No newline at end of file From 7c8aee339560758a1ec47692d4f459a92b171b02 Mon Sep 17 00:00:00 2001 From: HokutoTateyama Date: Sun, 11 Aug 2019 18:31:20 +0900 Subject: [PATCH 09/21] Update README and line space --- .coveragerc | 2 +- .travis.yml | 2 +- README.md | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 102 insertions(+), 4 deletions(-) diff --git a/.coveragerc b/.coveragerc index d492764..8a2220c 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,2 +1,2 @@ [run] -source = ife \ No newline at end of file +source = ife diff --git a/.travis.yml b/.travis.yml index b1d5fe9..553f72c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,4 +16,4 @@ install: script: - coverage run -m unittest discover after_success: - - coveralls \ No newline at end of file + - coverallspoetrey diff --git a/README.md b/README.md index cda9325..a5090a0 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,104 @@ +# Image Feature Extractor(IFE) [![Coverage Status](https://coveralls.io/repos/github/Collonville/ImageFeatureExtractor/badge.svg)](https://coveralls.io/github/Collonville/ImageFeatureExtractor) [![Build Status](https://travis-ci.org/Collonville/ImageFeatureExtractor.svg?branch=develop)](https://travis-ci.org/Collonville/ImageFeatureExtractor) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/115c65043153459cbfc5026ea53be08d)](https://www.codacy.com/app/Collonville/ImageFeatureExtractor?utm_source=github.com&utm_medium=referral&utm_content=Collonville/ImageFeatureExtractor&utm_campaign=Badge_Grade) -# ImageFeatureExtractor -Want a great image features??? Use IFE package!!! +## What is this???? +`IFE` is a package to get an image feature more easily for Python. It contains many kinds of feature extract algorithms. + + +## 1. Features +### Color Moment +- Mean, Median, Variance, Skewness, Kurtosis of `RGB, HSV, HSL, CMY` + +## 2. Examples +Import the basic image reader of IFE. +```python +from ife.io.io import ImageReader +``` + +### 2.1 Get Moment +Add a image file path to `read_from_single_file()`. This will return basic features class. + +And now! You can get a RGB color moment feature from image!! +```python +>>> features = ImageReader.read_from_single_file("ife/data/small_rgb.jpg") +>>> features.moment() +array([[ 0.57745098, 0.52156863, 0.55980392], + [ 0.58823529, 0.48823529, 0.54901961], + [ 0.15220588, 0.12136101, 0.12380911], + [-0.01944425, 0.18416571, 0.04508015], + [-1.94196824, -1.55209335, -1.75586748]]) +``` + +Also, you can get an `flatten vector, dictionary, or pandas` +```python +>>> features.moment(output_type="one_col") +array([ 0.57745098, 0.52156863, 0.55980392, 0.58823529, 0.48823529, + 0.54901961, 0.15220588, 0.12136101, 0.12380911, -0.01944425, + 0.18416571, 0.04508015, -1.94196824, -1.55209335, -1.75586748]) + +>>> features.moment(output_type="dict") +defaultdict(, {'mean': {'R': 0.57745098039215681, 'G': 0.52156862745098043, 'B': 0.55980392156862746}, 'median': {'R': 0.58823529411764708, 'G': 0.48823529411764705, 'B': 0.5490196078431373}, 'var': {'R': 0.15220588235294119, 'G': 0.12136101499423299, 'B': 0.12380911188004615}, 'skew': {'R': -0.019444250980856902, 'G': 0.18416570783012232, 'B': 0.045080152334687214}, 'kurtosis': {'R': -1.9419682406751135, 'G': -1.5520933544103905, 'B': -1.7558674751807395}}) + +>>> features.moment(output_type="pandas") + mean median var skew kurtosis +R 0.577451 0.588235 0.152206 -0.019444 -1.941968 +G 0.521569 0.488235 0.121361 0.184166 -1.552093 +B 0.559804 0.549020 0.123809 0.045080 -1.755867 +``` + +> No! I want a HSV Color space feature :( + +It can set another color space! Default will be RGB. +```python +>>> features.moment(output_type="one_col", color_space="CMY") +array([ 0.42254902, 0.47843137, 0.44019608, 0.41176471, 0.51176471, + 0.45098039, 0.15220588, 0.12136101, 0.12380911, 0.01944425, + -0.18416571, -0.04508015, -1.94196824, -1.55209335, -1.75586748]) + +>>> features.moment(output_type="dict", color_space="HSL") +defaultdict(, {'mean': {'H': 0.50798329143793874, 'S': 0.52775831413836383, 'L': 0.61421568627450984}, 'median': {'H': 0.51915637553935423, 'S': 0.62898601603182969, 'L': 0.52156862745098043}, 'var': {'H': 0.13290200013401141, 'S': 0.10239897927552907, 'L': 0.051550124951941563}, 'skew': {'H': -0.078898095002588917, 'S': -0.83203104238315984, 'L': 1.0202366337483093}, 'kurtosis': {'H': -1.2599104562470791, 'S': -0.87111810912637022, 'L': -0.7502836585891588}}) + +>>> features.moment(output_type="pandas", color_space="HSV") + mean median var skew kurtosis +H 0.507983 0.519156 0.132902 -0.078898 -1.259910 +S 0.595236 0.749543 0.122723 -1.028366 -0.768867 +V 0.855882 0.864706 0.013867 -0.155656 -1.498179 +``` + +## 3. Future work +### IO +- Read from URL links +- Read from Base64 +- Sliding window +- Video files + +### Color space +- CMYK +- CIE Lab +- XYZ + +### Features +- Value normalize +- Average Gradient +- LBP +- Histogram +- Color harmony +- Entropy +- Brightness measure +- Contrast measure +- Saturation measure +- Colourfulness +- Naturalness +- Color fidelity metric +- Saliency map +- Fisher vector +- VGG16, 19 layer feature +- and more... + +## 4. Author +@Collonville + +## 5. Licence +BSD-3-Clause From 95f4214ae4e771165ae7cbdbec59e7fbeca40640 Mon Sep 17 00:00:00 2001 From: HokutoTateyama Date: Sun, 18 Aug 2019 15:41:01 +0900 Subject: [PATCH 10/21] Update README for code quality --- README.md | 51 +++++++++++++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index a5090a0..8573e26 100644 --- a/README.md +++ b/README.md @@ -3,13 +3,12 @@ [![Build Status](https://travis-ci.org/Collonville/ImageFeatureExtractor.svg?branch=develop)](https://travis-ci.org/Collonville/ImageFeatureExtractor) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/115c65043153459cbfc5026ea53be08d)](https://www.codacy.com/app/Collonville/ImageFeatureExtractor?utm_source=github.com&utm_medium=referral&utm_content=Collonville/ImageFeatureExtractor&utm_campaign=Badge_Grade) -## What is this???? +## What is this? `IFE` is a package to get an image feature more easily for Python. It contains many kinds of feature extract algorithms. - ## 1. Features ### Color Moment -- Mean, Median, Variance, Skewness, Kurtosis of `RGB, HSV, HSL, CMY` +- Mean, Median, Variance, Skewness, Kurtosis of `RGB, HSV, HSL, CMY` ## 2. Examples Import the basic image reader of IFE. @@ -69,33 +68,33 @@ V 0.855882 0.864706 0.013867 -0.155656 -1.498179 ## 3. Future work ### IO -- Read from URL links -- Read from Base64 -- Sliding window -- Video files +- Read from URL links +- Read from Base64 +- Sliding window +- Video files ### Color space -- CMYK -- CIE Lab -- XYZ +- CMYK +- CIE Lab +- XYZ ### Features -- Value normalize -- Average Gradient -- LBP -- Histogram -- Color harmony -- Entropy -- Brightness measure -- Contrast measure -- Saturation measure -- Colourfulness -- Naturalness -- Color fidelity metric -- Saliency map -- Fisher vector -- VGG16, 19 layer feature -- and more... +- Value normalize +- Average Gradient +- LBP +- Histogram +- Color harmony +- Entropy +- Brightness measure +- Contrast measure +- Saturation measure +- Colourfulness +- Naturalness +- Color fidelity metric +- Saliency map +- Fisher vector +- VGG16, 19 layer feature +- and more... ## 4. Author @Collonville From a04778cf6ffcd3622705c1739350fa2f43b8f61d Mon Sep 17 00:00:00 2001 From: HokutoTateyama Date: Sun, 18 Aug 2019 15:44:53 +0900 Subject: [PATCH 11/21] Update for Potery build --- .gitignore | 8 ++++++-- .travis.yml | 6 +++++- pyproject.toml | 6 ++++-- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index bfa62d4..eeb5542 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,12 @@ -#Python byte code +# Python byte code __pycache__/ *.py[cod] # PyCharm .idea/ -.coverage \ No newline at end of file +.coverage + +# Poetry build file +.dist/ +dist/ diff --git a/.travis.yml b/.travis.yml index 553f72c..59141f6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,11 @@ language: python python: - "3.6" - - "3.6-dev" # 3.6 development branch + - "3.6-dev" + - "3.7" + - "3.7-dev" + - "3.8-dev" + - "nightly" branches: only: - master diff --git a/pyproject.toml b/pyproject.toml index a33d416..6eb13c7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [tool.poetry] -name = "imagefeatureextractor" +name = "ife" version = "0.1.0" description = "You can get a nice global image feature!!" authors = ["HokutoTateyama "] @@ -8,8 +8,10 @@ license = "BSD-3-Clause" readme = "README.md" classifiers =[ "Development Status :: 2 - Pre-Alpha", - "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", "Topic :: Scientific/Engineering" ] From 4a6e5eab34f13c25a52139e966e5e1a9c0e8e4f5 Mon Sep 17 00:00:00 2001 From: HokutoTateyama Date: Sun, 18 Aug 2019 20:32:52 +0900 Subject: [PATCH 12/21] Add mypy --- .gitignore | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.gitignore b/.gitignore index eeb5542..12c2587 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,8 @@ __pycache__/ # Poetry build file .dist/ dist/ + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json From b21cc17439111c104becdd60e59ea7f5467df31d Mon Sep 17 00:00:00 2001 From: HokutoTateyama Date: Sun, 18 Aug 2019 20:45:36 +0900 Subject: [PATCH 13/21] Add type hints --- ife/features/features.py | 31 ++++++++++++------------- ife/features/moment.py | 35 +++++++++++++---------------- ife/features/tests/test_features.py | 4 ++-- ife/features/tests/test_moment.py | 10 ++++----- ife/io/tests/test_io.py | 8 +++---- ife/util/array.py | 7 +++--- ife/util/tests/test_array.py | 14 ++++++------ pyproject.toml | 3 +-- usage.py | 6 ++++- 9 files changed, 57 insertions(+), 61 deletions(-) diff --git a/ife/features/features.py b/ife/features/features.py index ef07e84..a4ff9cb 100644 --- a/ife/features/features.py +++ b/ife/features/features.py @@ -1,10 +1,9 @@ from collections import defaultdict +from typing import Optional, Union, List import numpy as np import pandas as pd -from typing import Optional, Union - from ife.util.array import to_2d_array, convert_color_space_from_rgb from . import moment @@ -12,34 +11,32 @@ class Features: np_image: np.ndarray - def __init__(self, np_image): + def __init__(self, np_image: np.ndarray) -> None: self.np_image = np_image def moment( self, - required_methods: Optional[Union[str, list]] = None, - color_space: Optional[str] = "RGB", + required_methods: Optional[List[str]] = None, + color_space: Optional[str] = None, output_type: Optional[str] = None, - ): + ) -> Union[np.ndarray, dict, pd.DataFrame]: + color_space = "RGB" if color_space is None else color_space + np_2d_image = convert_color_space_from_rgb( to_2d_array(self.np_image), color_space ) - method_list = moment.get_method(required_methods) - - moment_value = np.array([method(np_2d_image) for method in method_list]) + moments, method_list = moment.get_moments(required_methods, np_2d_image) - if output_type is None or output_type is "": - return moment_value + if output_type is None or output_type == "": + return moments elif output_type == "one_col": - return moment_value.flatten() + return moments.flatten() - dict_result = defaultdict(dict) + dict_result = defaultdict(dict) # type: defaultdict for method_idx, method in enumerate(method_list): - for index in range(moment_value.shape[1]): - dict_result[method.__name__][color_space[index]] = moment_value[ - method_idx, index - ] + for index in range(moments.shape[1]): + dict_result[method][color_space[index]] = moments[method_idx, index] if output_type == "dict": return dict_result diff --git a/ife/features/moment.py b/ife/features/moment.py index e8c40f7..b3ecaa2 100644 --- a/ife/features/moment.py +++ b/ife/features/moment.py @@ -1,40 +1,35 @@ -from typing import Optional, Union +from typing import Optional, List, Tuple import numpy as np from scipy import stats -def get_method(method: Optional[Union[str, list]] = None): - if method is None: - return MOMENT_METHODS.values() - else: - return [MOMENT_METHODS[method_name] for method_name in [method]] +def get_moments( + methods: Optional[List[str]], np_2d_image: np.ndarray +) -> Tuple[np.ndarray, List[str]]: + if methods is None: + methods = ["mean", "median", "var", "skew", "kurtosis"] + moments = np.array([eval(method)(np_2d_image) for method in methods]) -def mean(np_2d_image: np.ndarray): + return moments, methods + + +def mean(np_2d_image: np.ndarray) -> np.ndarray: return np.mean(np_2d_image, axis=0) -def median(np_2d_image: np.ndarray): +def median(np_2d_image: np.ndarray) -> np.ndarray: return np.median(np_2d_image, axis=0) -def var(np_2d_image: np.ndarray): +def var(np_2d_image: np.ndarray) -> np.ndarray: return np.var(np_2d_image, axis=0) -def skew(np_2d_image: np.ndarray): +def skew(np_2d_image: np.ndarray) -> np.ndarray: return stats.skew(np_2d_image, axis=0) -def kurtosis(np_2d_image: np.ndarray): +def kurtosis(np_2d_image: np.ndarray) -> np.ndarray: return stats.kurtosis(np_2d_image, axis=0) - - -MOMENT_METHODS = { - "Mean": mean, - "Median": median, - "Var": var, - "Skew": skew, - "kurtosis": kurtosis, -} diff --git a/ife/features/tests/test_features.py b/ife/features/tests/test_features.py index 021d24e..de3e91c 100644 --- a/ife/features/tests/test_features.py +++ b/ife/features/tests/test_features.py @@ -8,7 +8,7 @@ class TestMomentFeatures(unittest.TestCase): - def test_output_type(self): + def test_output_type(self) -> None: features = ImageReader.read_from_single_file("ife/data/small_rgb.jpg") moment = features.moment() @@ -19,7 +19,7 @@ def test_output_type(self): moment = features.moment(output_type="one_col") self.assertIs(np.ndarray, type(moment)) - self.assertEqual(np.zeros(15).shape, moment.shape) + self.assertEqual(np.zeros(15).shape, moment.shape) # type: ignore moment = features.moment(output_type="dict") self.assertIs(defaultdict, type(moment)) diff --git a/ife/features/tests/test_moment.py b/ife/features/tests/test_moment.py index 22d37bf..8f1ee5c 100644 --- a/ife/features/tests/test_moment.py +++ b/ife/features/tests/test_moment.py @@ -2,17 +2,17 @@ class TestMoment(unittest.TestCase): - def test_mean(self): + def test_mean(self) -> None: pass - def test_median(self): + def test_median(self) -> None: pass - def test_var(self): + def test_var(self) -> None: pass - def test_skew(self): + def test_skew(self) -> None: pass - def test_kurtosis(self): + def test_kurtosis(self) -> None: pass diff --git a/ife/io/tests/test_io.py b/ife/io/tests/test_io.py index db1f11d..50a52a2 100644 --- a/ife/io/tests/test_io.py +++ b/ife/io/tests/test_io.py @@ -4,15 +4,15 @@ class TestIO(unittest.TestCase): - def test_undefined_type(self): + def test_undefined_type(self) -> None: with self.assertRaises(ValueError): - ImageReader().read_from_single_file(["", ""]) + ImageReader().read_from_single_file(["", ""]) # type: ignore - def test_unreachable_file(self): + def test_unreachable_file(self) -> None: with self.assertRaises(FileExistsError): ImageReader().read_from_single_file("../../data/none") - def test_reachable_file(self): + def test_reachable_file(self) -> None: expected = Features actual = ImageReader().read_from_single_file("ife/data/small_rgb.jpg") diff --git a/ife/util/array.py b/ife/util/array.py index 60e1c59..3d66fdc 100644 --- a/ife/util/array.py +++ b/ife/util/array.py @@ -1,8 +1,9 @@ import colour import numpy as np +from typing import Optional -def to_2d_array(array: np.ndarray): +def to_2d_array(array: np.ndarray) -> np.ndarray: dimension = len(array.shape) if dimension == 1: @@ -14,9 +15,9 @@ def to_2d_array(array: np.ndarray): def convert_color_space_from_rgb( - np_image: np.ndarray, dest_color_space: str + np_image: np.ndarray, dest_color_space: Optional[str] ) -> np.ndarray: - if dest_color_space == "RGB": + if dest_color_space is None or dest_color_space == "RGB": return np_image elif dest_color_space == "HSV": return colour.RGB_to_HSV(np_image) diff --git a/ife/util/tests/test_array.py b/ife/util/tests/test_array.py index 01aa145..ac2ba57 100644 --- a/ife/util/tests/test_array.py +++ b/ife/util/tests/test_array.py @@ -7,17 +7,17 @@ class Test2dArray(unittest.TestCase): - def test_1dim(self): + def test_1dim(self) -> None: with self.assertRaises(ValueError): to_2d_array(np.arange(4.0)) - def test_2dim(self): + def test_2dim(self) -> None: expected = np.array([[0, 1, 2], [3, 4, 5]], np.float) actual = to_2d_array(np.arange(6.0).reshape(2, 3)) np.testing.assert_array_equal(expected, actual) - def test_3dim(self): + def test_3dim(self) -> None: expected = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]], np.float) actual = to_2d_array(np.arange(12.0).reshape(2, 2, 3)) @@ -25,7 +25,7 @@ def test_3dim(self): class TestColorConvertFromRGB(unittest.TestCase): - def test_rgb_2_rgb(self): + def test_rgb_2_rgb(self) -> None: expected = np.array([0, 0, 0]) actual = convert_color_space_from_rgb(np.array([0, 0, 0]), "RGB") @@ -36,7 +36,7 @@ def test_rgb_2_rgb(self): np.testing.assert_array_equal(expected, actual) - def test_rgb_2_hsv(self): + def test_rgb_2_hsv(self) -> None: filter_warnings(python_warnings=True) expected = np.array([0, 0, 0]) actual = convert_color_space_from_rgb(np.array([0, 0, 0]), "HSV") @@ -48,8 +48,8 @@ def test_rgb_2_hsv(self): np.testing.assert_array_almost_equal(expected, actual, decimal=3) - def test_rgb_2_hsl(self): + def test_rgb_2_hsl(self) -> None: pass - def test_rgb_2_cmy(self): + def test_rgb_2_cmy(self) -> None: pass diff --git a/pyproject.toml b/pyproject.toml index 6eb13c7..e14597e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [tool.poetry] name = "ife" version = "0.1.0" -description = "You can get a nice global image feature!!" +description = "You can get a nice global image feature!" authors = ["HokutoTateyama "] repository = "https://github.com/Collonville/ImageFeatureExtractor" license = "BSD-3-Clause" @@ -11,7 +11,6 @@ classifiers =[ "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", "Topic :: Scientific/Engineering" ] diff --git a/usage.py b/usage.py index c8f067b..e2c2128 100644 --- a/usage.py +++ b/usage.py @@ -4,7 +4,11 @@ def main(): features = ImageReader.read_from_single_file("ife/data/small_rgb.jpg") - print(features.moment(output_type="pandas")) + print( + features.moment( + required_methods=["var", "mean"], output_type="one_col", color_space="HSV" + ) + ) if __name__ == "__main__": From 453347c70cacbcb78cb49fc5262a36ff40e30044 Mon Sep 17 00:00:00 2001 From: HokutoTateyama Date: Sun, 18 Aug 2019 20:55:19 +0900 Subject: [PATCH 14/21] Add code linter --- .travis.yml | 29 +++++++++++--- poetry.lock | 106 ++++++++++++++++++++++++++++++++++++++++++++++++- pyproject.toml | 2 + 3 files changed, 130 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 59141f6..aecbede 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ language: python + python: - "3.6" - "3.6-dev" @@ -6,18 +7,34 @@ python: - "3.7-dev" - "3.8-dev" - "nightly" + branches: only: - master - develop -# command to install dependencies + +stages: + - lint + - test + +jobs: + include: + - stage: lint + sctipt: + - flake8 ife --ignore E501 + - black --diff ife + - mypy --strict-optional --disallow-untyped-defs --disallow-untyped-calls --ignore-missing-imports --no-incremental ife + - stage: test + install: + - poetry install -v + - pip install coveralls + script: + - coverage run -m unittest discover + before_install: - pip install --upgrade pip + - pip install black - pip install poetry -install: - - poetry install -v - - pip install coveralls -script: - - coverage run -m unittest discover + after_success: - coverallspoetrey diff --git a/poetry.lock b/poetry.lock index 65b5905..d80ac56 100644 --- a/poetry.lock +++ b/poetry.lock @@ -10,6 +10,57 @@ version = "0.3.13" scipy = ">=0.16.0" six = ">=1.10.0" +[[package]] +category = "main" +description = "Discover and load entry points from installed packages." +name = "entrypoints" +optional = false +python-versions = ">=2.7" +version = "0.3" + +[[package]] +category = "main" +description = "the modular source code checker: pep8, pyflakes and co" +name = "flake8" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "3.7.8" + +[package.dependencies] +entrypoints = ">=0.3.0,<0.4.0" +mccabe = ">=0.6.0,<0.7.0" +pycodestyle = ">=2.5.0,<2.6.0" +pyflakes = ">=2.1.0,<2.2.0" + +[[package]] +category = "main" +description = "McCabe checker, plugin for flake8" +name = "mccabe" +optional = false +python-versions = "*" +version = "0.6.1" + +[[package]] +category = "main" +description = "Optional static typing for Python" +name = "mypy" +optional = false +python-versions = "*" +version = "0.720" + +[package.dependencies] +mypy-extensions = ">=0.4.0,<0.5.0" +typed-ast = ">=1.4.0,<1.5.0" +typing-extensions = ">=3.7.4" + +[[package]] +category = "main" +description = "Experimental type system extensions for programs checked with the mypy typechecker." +name = "mypy-extensions" +optional = false +python-versions = "*" +version = "0.4.1" + [[package]] category = "main" description = "NumPy is the fundamental package for array computing with Python." @@ -39,6 +90,22 @@ optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" version = "6.1.0" +[[package]] +category = "main" +description = "Python style guide checker" +name = "pycodestyle" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "2.5.0" + +[[package]] +category = "main" +description = "passive checker of Python programs" +name = "pyflakes" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "2.1.1" + [[package]] category = "main" description = "Extensions to the standard Python datetime module" @@ -77,16 +144,53 @@ optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*" version = "1.12.0" +[[package]] +category = "main" +description = "a fork of Python 2 and 3 ast modules with type comment support" +name = "typed-ast" +optional = false +python-versions = "*" +version = "1.4.0" + +[[package]] +category = "main" +description = "Type Hints for Python" +name = "typing" +optional = false +python-versions = "*" +version = "3.7.4" + +[[package]] +category = "main" +description = "Backported and Experimental Type Hints for Python 3.5+" +name = "typing-extensions" +optional = false +python-versions = "*" +version = "3.7.4" + +[package.dependencies] +typing = ">=3.7.4" + [metadata] -content-hash = "81b6833e373b7dbb66bd7f09af14561d5de0cf608032895171f512748e284faf" +content-hash = "ddc1a4ee3393b4fbc98b3b52107149d1c7580ce48a48ffc74babc22a5f6f6c6f" python-versions = "^3.6" [metadata.hashes] colour-science = ["4f03919b96a055c08b4cd174878224ae89680f721e13d0cefe98ce026491bc2d", "5f6b25a3bdd2d5fa7bca81a1b8b1a1418cff5d238622c86449dc6b52cd2819fa"] +entrypoints = ["589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19", "c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451"] +flake8 = ["19241c1cbc971b9962473e4438a2ca19749a7dd002dd1a946eaba171b4114548", "8e9dfa3cecb2400b3738a42c54c3043e821682b9c840b0448c0503f781130696"] +mccabe = ["ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", "dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"] +mypy = ["0107bff4f46a289f0e4081d59b77cef1c48ea43da5a0dbf0005d54748b26df2a", "07957f5471b3bb768c61f08690c96d8a09be0912185a27a68700f3ede99184e4", "10af62f87b6921eac50271e667cc234162a194e742d8e02fc4ddc121e129a5b0", "11fd60d2f69f0cefbe53ce551acf5b1cec1a89e7ce2d47b4e95a84eefb2899ae", "15e43d3b1546813669bd1a6ec7e6a11d2888db938e0607f7b5eef6b976671339", "352c24ba054a89bb9a35dd064ee95ab9b12903b56c72a8d3863d882e2632dc76", "437020a39417e85e22ea8edcb709612903a9924209e10b3ec6d8c9f05b79f498", "49925f9da7cee47eebf3420d7c0e00ec662ec6abb2780eb0a16260a7ba25f9c4", "6724fcd5777aa6cebfa7e644c526888c9d639bd22edd26b2a8038c674a7c34bd", "7a17613f7ea374ab64f39f03257f22b5755335b73251d0d253687a69029701ba", "cdc1151ced496ca1496272da7fc356580e95f2682be1d32377c22ddebdf73c91"] +mypy-extensions = ["37e0e956f41369209a3d5f34580150bcacfabaa57b33a15c0b25f4b5725e0812", "b16cabe759f55e3409a7d231ebd2841378fb0c27a5d1994719e340e4f429ac3e"] numpy = ["03e311b0a4c9f5755da7d52161280c6a78406c7be5c5cc7facfbcebb641efb7e", "0cdd229a53d2720d21175012ab0599665f8c9588b3b8ffa6095dd7b90f0691dd", "312bb18e95218bedc3563f26fcc9c1c6bfaaf9d453d15942c0839acdd7e4c473", "464b1c48baf49e8505b1bb754c47a013d2c305c5b14269b5c85ea0625b6a988a", "5adfde7bd3ee4864536e230bcab1c673f866736698724d5d28c11a4d63672658", "7724e9e31ee72389d522b88c0d4201f24edc34277999701ccd4a5392e7d8af61", "8d36f7c53ae741e23f54793ffefb2912340b800476eb0a831c6eb602e204c5c4", "910d2272403c2ea8a52d9159827dc9f7c27fb4b263749dca884e2e4a8af3b302", "951fefe2fb73f84c620bec4e001e80a80ddaa1b84dce244ded7f1e0cbe0ed34a", "9588c6b4157f493edeb9378788dcd02cb9e6a6aeaa518b511a1c79d06cbd8094", "9ce8300950f2f1d29d0e49c28ebfff0d2f1e2a7444830fbb0b913c7c08f31511", "be39cca66cc6806652da97103605c7b65ee4442c638f04ff064a7efd9a81d50a", "c3ab2d835b95ccb59d11dfcd56eb0480daea57cdf95d686d22eff35584bc4554", "eb0fc4a492cb896346c9e2c7a22eae3e766d407df3eb20f4ce027f23f76e4c54", "ec0c56eae6cee6299f41e780a0280318a93db519bbb2906103c43f3e2be1206c", "f4e4612de60a4f1c4d06c8c2857cdcb2b8b5289189a12053f37d3f41f06c60d0"] pandas = ["074a032f99bb55d178b93bd98999c971542f19317829af08c99504febd9e9b8b", "20f1728182b49575c2f6f681b3e2af5fac9e84abdf29488e76d569a7969b362e", "2745ba6e16c34d13d765c3657bb64fa20a0e2daf503e6216a36ed61770066179", "32c44e5b628c48ba17703f734d59f369d4cdcb4239ef26047d6c8a8bfda29a6b", "3b9f7dcee6744d9dcdd53bce19b91d20b4311bf904303fa00ef58e7df398e901", "544f2033250980fb6f069ce4a960e5f64d99b8165d01dc39afd0b244eeeef7d7", "58f9ef68975b9f00ba96755d5702afdf039dea9acef6a0cfd8ddcde32918a79c", "9023972a92073a495eba1380824b197ad1737550fe1c4ef8322e65fe58662888", "914341ad2d5b1ea522798efa4016430b66107d05781dbfe7cf05eba8f37df995", "9d151bfb0e751e2c987f931c57792871c8d7ff292bcdfcaa7233012c367940ee", "b932b127da810fef57d427260dde1ad54542c136c44b227a1e367551bb1a684b", "cfb862aa37f4dd5be0730731fdb8185ac935aba8b51bf3bd035658111c9ee1c9", "de7ecb4b120e98b91e8a2a21f186571266a8d1faa31d92421e979c7ca67d8e5c", "df7e1933a0b83920769611c5d6b9a1bf301e3fa6a544641c6678c67621fe9843"] pillow = ["0804f77cb1e9b6dbd37601cee11283bba39a8d44b9ddb053400c58e0c0d7d9de", "0ab7c5b5d04691bcbd570658667dd1e21ca311c62dcfd315ad2255b1cd37f64f", "0b3e6cf3ea1f8cecd625f1420b931c83ce74f00c29a0ff1ce4385f99900ac7c4", "0c6ce6ae03a50b0306a683696234b8bc88c5b292d4181ae365b89bd90250ab08", "1454ee7297a81c8308ad61d74c849486efa1badc543453c4b90db0bf99decc1c", "23efd7f83f2ad6036e2b9ef27a46df7e333de1ad9087d341d87e12225d0142b2", "365c06a45712cd723ec16fa4ceb32ce46ad201eb7bbf6d3c16b063c72b61a3ed", "38301fbc0af865baa4752ddae1bb3cbb24b3d8f221bf2850aad96b243306fa03", "3aef1af1a91798536bbab35d70d35750bd2884f0832c88aeb2499aa2d1ed4992", "3c86051d41d1c8b28b9dde08ac93e73aa842991995b12771b0af28da49086bbf", "3fe0ab49537d9330c9bba7f16a5f8b02da615b5c809cdf7124f356a0f182eccd", "406c856e0f6fc330322a319457d9ff6162834050cda2cf1eaaaea4b771d01914", "45a619d5c1915957449264c81c008934452e3fd3604e36809212300b2a4dab68", "49f90f147883a0c3778fd29d3eb169d56416f25758d0f66775db9184debc8010", "504f5334bfd974490a86fef3e3b494cd3c332a8a680d2f258ca03388b40ae230", "51fe9cfcd32c849c6f36ca293648f279fc5097ca8dd6e518b10df3a6a9a13431", "571b5a758baf1cb6a04233fb23d6cf1ca60b31f9f641b1700bfaab1194020555", "5ac381e8b1259925287ccc5a87d9cf6322a2dc88ae28a97fe3e196385288413f", "6052a9e9af4a9a2cc01da4bbee81d42d33feca2bde247c4916d8274b12bb31a4", "6153db744a743c0c8c91b8e3b9d40e0b13a5d31dbf8a12748c6d9bfd3ddc01ad", "6fd63afd14a16f5d6b408f623cc2142917a1f92855f0df997e09a49f0341be8a", "70acbcaba2a638923c2d337e0edea210505708d7859b87c2bd81e8f9902ae826", "70b1594d56ed32d56ed21a7fbb2a5c6fd7446cdb7b21e749c9791eac3a64d9e4", "76638865c83b1bb33bcac2a61ce4d13c17dba2204969dedb9ab60ef62bede686", "7b2ec162c87fc496aa568258ac88631a2ce0acfe681a9af40842fc55deaedc99", "7b403ea842b70c4fa0a4969a5d8d86e932c941095b7cda077ea68f7b98ead30b", "7be698a28175eae5354da94f5f3dc787d5efae6aca7ad1f286a781afde6a27dd", "7cee2cef07c8d76894ebefc54e4bb707dfc7f258ad155bd61d87f6cd487a70ff", "7d16d4498f8b374fc625c4037742fbdd7f9ac383fd50b06f4df00c81ef60e829", "82840783842b27933cc6388800cb547f31caf436f7e23384d456bdf5fc8dfe49", "8755e600b33f4e8c76a590b42acc35d24f4dc801a5868519ce569b9462d77598", "9159285ab4030c6f85e001468cb5886de05e6bd9304e9e7d46b983f7d2fad0cc", "b50bc1780681b127e28f0075dfb81d6135c3a293e0c1d0211133c75e2179b6c0", "b5aa19f1da16b4f5e47b6930053f08cba77ceccaed68748061b0ec24860e510c", "bd0582f831ad5bcad6ca001deba4568573a4675437db17c4031939156ff339fa", "cdd53acd3afb9878a2289a1b55807871f9877c81174ae0d3763e52f907131d25", "cfd40d8a4b59f7567620410f966bb1f32dc555b2b19f82a91b147fac296f645c", "e150c5aed6e67321edc6893faa6701581ca2d393472f39142a00e551bcd249a5", "e3ae410089de680e8f84c68b755b42bc42c0ceb8c03dbea88a5099747091d38e", "e403b37c6a253ebca5d0f2e5624643997aaae529dc96299162418ef54e29eb70", "e9046e559c299b395b39ac7dbf16005308821c2f24a63cae2ab173bd6aa11616", "ef6be704ae2bc8ad0ebc5cb850ee9139493b0fc4e81abcc240fb392a63ebc808", "f8dc19d92896558f9c4317ee365729ead9d7bbcf2052a9a19a3ef17abbb8ac5b"] +pycodestyle = ["95a2219d12372f05704562a14ec30bc76b05a5b297b21a5dfe3f6fac3491ae56", "e40a936c9a450ad81df37f549d676d127b1b66000a6c500caa2b085bc0ca976c"] +pyflakes = ["17dbeb2e3f4d772725c777fabc446d5634d1038f234e77343108ce445ea69ce0", "d976835886f8c5b31d47970ed689944a0262b5f3afa00a5a7b4dc81e5449f8a2"] python-dateutil = ["7e6584c74aeed623791615e26efd690f29817a27c73085b78e4bad02493df2fb", "c89805f6f4d64db21ed966fda138f8a5ed7a4fdbc1a8ee329ce1b74e3c74da9e"] pytz = ["26c0b32e437e54a18161324a2fca3c4b9846b74a8dccddd843113109e1116b32", "c894d57500a4cd2d5c71114aaab77dbab5eabd9022308ce5ac9bb93a60a6f0c7"] scipy = ["0baa64bf42592032f6f6445a07144e355ca876b177f47ad8d0612901c9375bef", "243b04730d7223d2b844bda9500310eecc9eda0cba9ceaf0cde1839f8287dfa8", "2643cfb46d97b7797d1dbdb6f3c23fe3402904e3c90e6facfe6a9b98d808c1b5", "396eb4cdad421f846a1498299474f0a3752921229388f91f60dc3eda55a00488", "3ae3692616975d3c10aca6d574d6b4ff95568768d4525f76222fb60f142075b9", "435d19f80b4dcf67dc090cc04fde2c5c8a70b3372e64f6a9c58c5b806abfa5a8", "46a5e55850cfe02332998b3aef481d33f1efee1960fe6cfee0202c7dd6fc21ab", "75b513c462e58eeca82b22fc00f0d1875a37b12913eee9d979233349fce5c8b2", "7ccfa44a08226825126c4ef0027aa46a38c928a10f0a8a8483c80dd9f9a0ad44", "89dd6a6d329e3f693d1204d5562dd63af0fd7a17854ced17f9cbc37d5b853c8d", "a81da2fe32f4eab8b60d56ad43e44d93d392da228a77e229e59b51508a00299c", "a9d606d11eb2eec7ef893eb825017fbb6eef1e1d0b98a5b7fc11446ebeb2b9b1", "ac37eb652248e2d7cbbfd89619dce5ecfd27d657e714ed049d82f19b162e8d45", "cbc0611699e420774e945f6a4e2830f7ca2b3ee3483fca1aa659100049487dd5", "d02d813ec9958ed63b390ded463163685af6025cb2e9a226ec2c477df90c6957", "dd3b52e00f93fd1c86f2d78243dfb0d02743c94dd1d34ffea10055438e63b99d"] six = ["3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", "d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"] +typed-ast = ["18511a0b3e7922276346bcb47e2ef9f38fb90fd31cb9223eed42c85d1312344e", "262c247a82d005e43b5b7f69aff746370538e176131c32dda9cb0f324d27141e", "2b907eb046d049bcd9892e3076c7a6456c93a25bebfe554e931620c90e6a25b0", "354c16e5babd09f5cb0ee000d54cfa38401d8b8891eefa878ac772f827181a3c", "4e0b70c6fc4d010f8107726af5fd37921b666f5b31d9331f0bd24ad9a088e631", "630968c5cdee51a11c05a30453f8cd65e0cc1d2ad0d9192819df9978984529f4", "66480f95b8167c9c5c5c87f32cf437d585937970f3fc24386f313a4c97b44e34", "71211d26ffd12d63a83e079ff258ac9d56a1376a25bc80b1cdcdf601b855b90b", "95bd11af7eafc16e829af2d3df510cecfd4387f6453355188342c3e79a2ec87a", "bc6c7d3fa1325a0c6613512a093bc2a2a15aeec350451cbdf9e1d4bffe3e3233", "cc34a6f5b426748a507dd5d1de4c1978f2eb5626d51326e43280941206c209e1", "d755f03c1e4a51e9b24d899561fec4ccaf51f210d52abdf8c07ee2849b212a36", "d7c45933b1bdfaf9f36c579671fec15d25b06c8398f113dab64c18ed1adda01d", "d896919306dd0aa22d0132f62a1b78d11aaf4c9fc5b3410d3c666b818191630a", "ffde2fbfad571af120fcbfbbc61c72469e72f550d676c3342492a9dfdefb8f12"] +typing = ["38566c558a0a94d6531012c8e917b1b8518a41e418f7f15f00e129cc80162ad3", "53765ec4f83a2b720214727e319607879fec4acde22c4fbb54fa2604e79e44ce", "84698954b4e6719e912ef9a42a2431407fe3755590831699debda6fba92aac55"] +typing-extensions = ["2ed632b30bb54fc3941c382decfd0ee4148f5c591651c9272473fea2c6397d95", "b1edbbf0652660e32ae780ac9433f4231e7339c7f9a8057d0f042fcbcea49b87", "d8179012ec2c620d3791ca6fe2bf7979d979acdbef1fca0bc56b37411db682ed"] diff --git a/pyproject.toml b/pyproject.toml index e14597e..353b146 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,6 +19,8 @@ python = "^3.6" Pillow = "^6.1" colour-science = "^0.3.13" pandas = "^0.25.0" +mypy = "^0.720.0" +flake8 = "^3.7" [tool.poetry.dev-dependencies] From 2a1d0d8e8d95875d6e6e371457befac5bc3a91b2 Mon Sep 17 00:00:00 2001 From: HokutoTateyama Date: Sun, 18 Aug 2019 21:16:00 +0900 Subject: [PATCH 15/21] Fix travis --- .travis.yml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index aecbede..d11930f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,6 +17,12 @@ stages: - lint - test +before_install: + - pip install --upgrade pip + - pip install black + - pip install poetry + - poetry install -v + jobs: include: - stage: lint @@ -26,15 +32,11 @@ jobs: - mypy --strict-optional --disallow-untyped-defs --disallow-untyped-calls --ignore-missing-imports --no-incremental ife - stage: test install: - - poetry install -v - pip install coveralls script: - coverage run -m unittest discover -before_install: - - pip install --upgrade pip - - pip install black - - pip install poetry + after_success: - coverallspoetrey From 2e22316f9d0b5732977899548325cadca67c2e37 Mon Sep 17 00:00:00 2001 From: HokutoTateyama Date: Sun, 18 Aug 2019 21:26:51 +0900 Subject: [PATCH 16/21] Fix travis --- .travis.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index d11930f..9f06c5e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,13 +15,18 @@ branches: stages: - lint - - test before_install: - pip install --upgrade pip - pip install black - pip install poetry + +install: - poetry install -v + - pip install coveralls +script: + - coverage run -m unittest discover + jobs: include: @@ -30,11 +35,6 @@ jobs: - flake8 ife --ignore E501 - black --diff ife - mypy --strict-optional --disallow-untyped-defs --disallow-untyped-calls --ignore-missing-imports --no-incremental ife - - stage: test - install: - - pip install coveralls - script: - - coverage run -m unittest discover From 9422994be46e8bfabee992281e6dc5cf4c4bd282 Mon Sep 17 00:00:00 2001 From: HokutoTateyama Date: Sun, 18 Aug 2019 21:31:51 +0900 Subject: [PATCH 17/21] Fix travis --- .travis.yml | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9f06c5e..640f46e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,30 +13,21 @@ branches: - master - develop -stages: - - lint - before_install: - pip install --upgrade pip - pip install black - pip install poetry +before_script: + - flake8 ife --ignore E501 + - black --diff ife + - mypy --strict-optional --disallow-untyped-defs --disallow-untyped-calls --ignore-missing-imports --no-incremental ife + install: - poetry install -v - pip install coveralls script: - coverage run -m unittest discover - -jobs: - include: - - stage: lint - sctipt: - - flake8 ife --ignore E501 - - black --diff ife - - mypy --strict-optional --disallow-untyped-defs --disallow-untyped-calls --ignore-missing-imports --no-incremental ife - - - after_success: - coverallspoetrey From 4fa0011d234bdc0f8db31083243237966874216e Mon Sep 17 00:00:00 2001 From: HokutoTateyama Date: Sun, 18 Aug 2019 22:35:48 +0900 Subject: [PATCH 18/21] Fix unsafe code --- ife/features/features.py | 4 ++-- ife/features/moment.py | 11 ++++++++++- usage.py | 6 +----- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/ife/features/features.py b/ife/features/features.py index a4ff9cb..131b0b0 100644 --- a/ife/features/features.py +++ b/ife/features/features.py @@ -16,7 +16,7 @@ def __init__(self, np_image: np.ndarray) -> None: def moment( self, - required_methods: Optional[List[str]] = None, + methods: Optional[List[str]] = None, color_space: Optional[str] = None, output_type: Optional[str] = None, ) -> Union[np.ndarray, dict, pd.DataFrame]: @@ -26,7 +26,7 @@ def moment( to_2d_array(self.np_image), color_space ) - moments, method_list = moment.get_moments(required_methods, np_2d_image) + moments, method_list = moment.get_moments(methods, np_2d_image) if output_type is None or output_type == "": return moments diff --git a/ife/features/moment.py b/ife/features/moment.py index b3ecaa2..fd784f3 100644 --- a/ife/features/moment.py +++ b/ife/features/moment.py @@ -10,7 +10,7 @@ def get_moments( if methods is None: methods = ["mean", "median", "var", "skew", "kurtosis"] - moments = np.array([eval(method)(np_2d_image) for method in methods]) + moments = np.array([METHODS[method](np_2d_image) for method in methods]) return moments, methods @@ -33,3 +33,12 @@ def skew(np_2d_image: np.ndarray) -> np.ndarray: def kurtosis(np_2d_image: np.ndarray) -> np.ndarray: return stats.kurtosis(np_2d_image, axis=0) + + +METHODS = { + "mean": mean, + "median": median, + "var": var, + "skew": skew, + "kurtosis": kurtosis, +} diff --git a/usage.py b/usage.py index e2c2128..74b5a88 100644 --- a/usage.py +++ b/usage.py @@ -4,11 +4,7 @@ def main(): features = ImageReader.read_from_single_file("ife/data/small_rgb.jpg") - print( - features.moment( - required_methods=["var", "mean"], output_type="one_col", color_space="HSV" - ) - ) + print(features.moment(methods=["var", "mean"], output_type="", color_space="HSV")) if __name__ == "__main__": From f9640a12797db4ea07a86d8af0ace8c5a287eac7 Mon Sep 17 00:00:00 2001 From: HokutoTateyama Date: Sun, 18 Aug 2019 22:49:56 +0900 Subject: [PATCH 19/21] Delete python3.8 --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 640f46e..b5b0083 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,8 +5,6 @@ python: - "3.6-dev" - "3.7" - "3.7-dev" - - "3.8-dev" - - "nightly" branches: only: From bb3dfc0b847838f03a5d640de618869d0eef74ec Mon Sep 17 00:00:00 2001 From: HokutoTateyama Date: Sun, 18 Aug 2019 22:50:14 +0900 Subject: [PATCH 20/21] Set version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 353b146..e8138c1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "ife" -version = "0.1.0" +version = "0.0.1" description = "You can get a nice global image feature!" authors = ["HokutoTateyama "] repository = "https://github.com/Collonville/ImageFeatureExtractor" From eca758be0b490bfa18b36ce5090391bc0a734fd4 Mon Sep 17 00:00:00 2001 From: HokutoTateyama Date: Sun, 18 Aug 2019 22:56:40 +0900 Subject: [PATCH 21/21] Set version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index e8138c1..649c41c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "ife" -version = "0.0.1" +version = "0.0.2" description = "You can get a nice global image feature!" authors = ["HokutoTateyama "] repository = "https://github.com/Collonville/ImageFeatureExtractor"