зеркало из
https://github.com/ssciwr/AMMICO.git
synced 2025-10-29 13:06:04 +02:00
Improve colors expression (#80)
* increased dash width * added new color_analysis notebook * added colorgram.py to dependencies * added first iteration of new color_check * added new version of color analysis * added webcolors to dependencies * added colormath * switched from colormath to colour-science * made delta_e algorithm user accessible * remove obsolete notebook * update docstrings and type hints * add color analysis module to API doc * renamed color_expressions to color_analysis * renamed test * updated color analysis notebook to adhere to the same style as other notebooks * updated test for new df orientation * refactored color analysis to comply with ammico workflow * updated color tests to comply with new class structure * added explanation to colors_analysis notebook * added class doc string * updated analysis explorer test to include empty image keyword as dash observer * fix typo and names, docstring and import * update doc and notebook explanation * add project url for pypi --------- Co-authored-by: Inga Ulusoy <inga.ulusoy@uni-heidelberg.de>
Этот коммит содержится в:
родитель
aedd166d7e
Коммит
1d9e1338ea
22
README.md
22
README.md
@ -36,7 +36,7 @@ Use pre-processed image files such as social media posts with comments and proce
|
||||
|
||||
The `AMMICO` package can be installed using pip:
|
||||
```
|
||||
pip install git+https://github.com/ssciwr/ammico.git
|
||||
pip install ammico
|
||||
```
|
||||
This will install the package and its dependencies locally.
|
||||
|
||||
@ -45,19 +45,21 @@ This will install the package and its dependencies locally.
|
||||
|
||||
There are sample notebooks in the `notebooks` folder for you to explore the package:
|
||||
1. Text extraction: Use the notebook `get-text-from-image.ipynb` to extract any text from the images. The text is directly translated into English. If the text should be further analysed, set the keyword `analyse_text` to `True` as demonstrated in the notebook.\
|
||||
**You can run this notebook on google colab: [Here](https://colab.research.google.com/github/ssciwr/ammico/blob/main/notebooks/get-text-from-image.ipynb)**
|
||||
**You can run this notebook on google colab: [Here](https://colab.research.google.com/github/ssciwr/ammico/blob/main/ammico/notebooks/get-text-from-image.ipynb)**
|
||||
Place the data files and google cloud vision API key in your google drive to access the data.
|
||||
1. Emotion recognition: Use the notebook `facial_expressions.ipynb` to identify if there are faces on the image, if they are wearing masks, and if they are not wearing masks also the race, gender and dominant emotion.
|
||||
**You can run this notebook on google colab: [Here](https://colab.research.google.com/github/ssciwr/ammico/blob/main/notebooks/facial_expressions.ipynb)**
|
||||
**You can run this notebook on google colab: [Here](https://colab.research.google.com/github/ssciwr/ammico/blob/main/ammico/notebooks/facial_expressions.ipynb)**
|
||||
Place the data files in your google drive to access the data.
|
||||
1. Content extraction: Use the notebook `image_summary.ipynb` to create captions for the images and ask questions about the image content.
|
||||
**You can run this notebook on google colab: [Here](https://colab.research.google.com/github/ssciwr/ammico/blob/main/notebooks/image_summary.ipynb)**
|
||||
**You can run this notebook on google colab: [Here](https://colab.research.google.com/github/ssciwr/ammico/blob/main/ammico/notebooks/image_summary.ipynb)**
|
||||
1. Multimodal content: Use the notebook `multimodal_search.ipynb` to find the best fitting images to an image or text query.
|
||||
**You can run this notebook on google colab: [Here](https://colab.research.google.com/github/ssciwr/ammico/blob/main/notebooks/multimodal_search.ipynb)**
|
||||
**You can run this notebook on google colab: [Here](https://colab.research.google.com/github/ssciwr/ammico/blob/main/ammico/notebooks/multimodal_search.ipynb)**
|
||||
1. Color analysis: Use the notebook `color_analysis.ipynb` to identify colors the image. The colors are then classified into the main named colors in the English language.
|
||||
**You can run this notebook on google colab: [Here](https://colab.research.google.com/github/ssciwr/ammico/blob/main/ammico/notebooks/colors_analysis.ipynb)**
|
||||
1. Object analysis: Use the notebook `ojects_expression.ipynb` to identify certain objects in the image. Currently, the following objects are being identified: person, bicycle, car, motorcycle, airplane, bus, train, truck, boat, traffic light, cell phone.
|
||||
**You can run this notebook on google colab: [Here](https://colab.research.google.com/github/ssciwr/ammico/blob/main/notebooks/objects_expression.ipynb)**
|
||||
|
||||
There are further notebooks that are currently of exploratory nature (`colors_expression.ipynb` to identify certain colors on the image). To crop social media posts use the `cropposts.ipynb` notebook.
|
||||
**You can run this notebook on google colab: [Here](https://colab.research.google.com/github/ssciwr/ammico/blob/main/ammico/notebooks/objects_expression.ipynb)**
|
||||
1. To crop social media posts use the `cropposts.ipynb` notebook.
|
||||
**You can run this notebook on google colab: [Here](https://colab.research.google.com/github/ssciwr/ammico/blob/main/ammico/notebooks/cropposts.ipynb)**
|
||||
|
||||
## Features
|
||||
### Text extraction
|
||||
@ -86,6 +88,10 @@ Emotion recognition is carried out using the [deepface](https://github.com/seren
|
||||
|
||||
Object detection is carried out using [cvlib](https://github.com/arunponnusamy/cvlib) and the [YOLOv4](https://github.com/AlexeyAB/darknet) model. This library detects faces, people, and several inanimate objects; we currently have restricted the output to person, bicycle, car, motorcycle, airplane, bus, train, truck, boat, traffic light, cell phone.
|
||||
|
||||
### Color/hue detection
|
||||
|
||||
Color detection is carried out using [colorgram.py](https://github.com/obskyr/colorgram.py) and [colour](https://github.com/vaab/colour) for the distance metric. The colors can be classified into the main named colors/hues in the English language, that are red, green, blue, yellow, cyan, orange, purple, pink, brown, grey, white, black.
|
||||
|
||||
### Cropping of posts
|
||||
|
||||
Social media posts can automatically be cropped to remove further comments on the page and restrict the textual content to the first comment only.
|
||||
118
ammico/colors.py
Обычный файл
118
ammico/colors.py
Обычный файл
@ -0,0 +1,118 @@
|
||||
import numpy as np
|
||||
import webcolors
|
||||
import pandas as pd
|
||||
from collections import defaultdict
|
||||
import colorgram
|
||||
import colour
|
||||
from ammico.utils import get_color_table, AnalysisMethod
|
||||
|
||||
|
||||
class ColorDetector(AnalysisMethod):
|
||||
def __init__(
|
||||
self,
|
||||
subdict: dict,
|
||||
delta_e_method: str = "CIE 1976",
|
||||
) -> None:
|
||||
"""Color Analysis class, analyse hue and identify named colors.
|
||||
|
||||
Args:
|
||||
subdict (dict): The dictionary containing the image path.
|
||||
delta_e_method (str): The calculation method used for assigning the
|
||||
closest color name, defaults to "CIE 1976".
|
||||
"""
|
||||
super().__init__(subdict)
|
||||
self.subdict.update(self.set_keys())
|
||||
self.merge_color = True
|
||||
self.n_colors = 100
|
||||
self.delta_e_method = delta_e_method
|
||||
|
||||
def set_keys(self) -> dict:
|
||||
colors = {
|
||||
"red": 0,
|
||||
"green": 0,
|
||||
"blue": 0,
|
||||
"yellow": 0,
|
||||
"cyan": 0,
|
||||
"orange": 0,
|
||||
"purple": 0,
|
||||
"pink": 0,
|
||||
"brown": 0,
|
||||
"grey": 0,
|
||||
"white": 0,
|
||||
"black": 0,
|
||||
}
|
||||
return colors
|
||||
|
||||
def analyse_image(self):
|
||||
"""
|
||||
Uses the colorgram library to extract the n most common colors from the images.
|
||||
One problem is, that the most common colors are taken before beeing categorized,
|
||||
so for small values it might occur that the ten most common colors are shades of grey,
|
||||
while other colors are present but will be ignored. Because of this n_colors=100 was chosen as default.
|
||||
|
||||
The colors are then matched to the closest color in the CSS3 color list using the delta-e metric.
|
||||
They are then merged into one data frame.
|
||||
The colors can be reduced to a smaller list of colors using the get_color_table function.
|
||||
These colors are: "red", "green", "blue", "yellow","cyan", "orange", "purple", "pink", "brown", "grey", "white", "black".
|
||||
|
||||
Returns:
|
||||
dict: Dictionary with color names as keys and percentage of color in image as values.
|
||||
"""
|
||||
filename = self.subdict["filename"]
|
||||
|
||||
colors = colorgram.extract(filename, self.n_colors)
|
||||
for color in colors:
|
||||
rgb_name = self.rgb2name(
|
||||
color.rgb,
|
||||
merge_color=self.merge_color,
|
||||
delta_e_method=self.delta_e_method,
|
||||
)
|
||||
self.subdict[rgb_name] += round(color.proportion, 2)
|
||||
|
||||
return self.subdict
|
||||
|
||||
def rgb2name(
|
||||
self, c, merge_color: bool = True, delta_e_method: str = "CIE 1976"
|
||||
) -> str:
|
||||
"""Take an rgb color as input and return the closest color name from the CSS3 color list.
|
||||
|
||||
Args:
|
||||
c (Union[List,tuple]): RGB value.
|
||||
merge_color (bool, Optional): Whether color name should be reduced, defaults to True.
|
||||
Returns:
|
||||
str: Closest matching color name.
|
||||
"""
|
||||
if len(c) != 3:
|
||||
raise ValueError("Input color must be a list or tuple of length 3 (RGB).")
|
||||
|
||||
h_color = "#{:02x}{:02x}{:02x}".format(int(c[0]), int(c[1]), int(c[2]))
|
||||
try:
|
||||
output_color = webcolors.hex_to_name(h_color, spec="css3")
|
||||
output_color = output_color.lower().replace("grey", "gray")
|
||||
except ValueError:
|
||||
delta_e_lst = []
|
||||
filtered_colors = webcolors.CSS3_NAMES_TO_HEX
|
||||
|
||||
for _, img_hex in filtered_colors.items():
|
||||
cur_clr = webcolors.hex_to_rgb(img_hex)
|
||||
# calculate color Delta-E
|
||||
delta_e = colour.delta_E(c, cur_clr, method=delta_e_method)
|
||||
delta_e_lst.append(delta_e)
|
||||
# find lowest delta-e
|
||||
min_diff = np.argsort(delta_e_lst)[0]
|
||||
output_color = (
|
||||
str(list(filtered_colors.items())[min_diff][0])
|
||||
.lower()
|
||||
.replace("grey", "gray")
|
||||
)
|
||||
|
||||
# match color to reduced list:
|
||||
if merge_color:
|
||||
for reduced_key, reduced_color_sub_list in get_color_table().items():
|
||||
if str(output_color).lower() in [
|
||||
str(color_name).lower()
|
||||
for color_name in reduced_color_sub_list["ColorName"]
|
||||
]:
|
||||
output_color = reduced_key.lower()
|
||||
break
|
||||
return output_color
|
||||
24
ammico/data/Color_tables.csv
Обычный файл
24
ammico/data/Color_tables.csv
Обычный файл
@ -0,0 +1,24 @@
|
||||
Pink;Pink;purple;purple;red;red;orange;orange;yellow;yellow;green;green;cyan;cyan;blue;blue;brown;brown;white;white;grey;grey;black;black
|
||||
ColorName;HEX;ColorName;HEX;ColorName;HEX;ColorName;HEX;ColorName;HEX;ColorName;HEX;ColorName;HEX;ColorName;HEX;ColorName;HEX;ColorName;HEX;ColorName;HEX;ColorName;HEX
|
||||
Pink;#FFC0CB;Lavender;#E6E6FA;LightSalmon;#FFA07A;Orange;#FFA500;Gold;#FFD700;GreenYellow;#ADFF2F;Aqua;#00FFFF;CadetBlue;#5F9EA0;Cornsilk;#FFF8DC;White;#FFFFFF;Gainsboro;#DCDCDC;Black;#000000
|
||||
LightPink;#FFB6C1;Thistle;#D8BFD8;Salmon;#FA8072;DarkOrange;#FF8C00;Yellow;#FFFF00;Chartreuse;#7FFF00;Cyan;#00FFFF;SteelBlue;#4682B4;BlanchedAlmond;#FFEBCD;Snow;#FFFAFA;LightGray;#D3D3D3;;
|
||||
HotPink;#FF69B4;Plum;#DDA0DD;DarkSalmon;#E9967A;Coral;#FF7F50;LightYellow;#FFFFE0;LawnGreen;#7CFC00;LightCyan;#E0FFFF;LightSteelBlue;#B0C4DE;Bisque;#FFE4C4;HoneyDew;#F0FFF0;Silver;#C0C0C0;;
|
||||
DeepPink;#FF1493;Orchid;#DA70D6;LightCoral;#F08080;Tomato;#FF6347;LemonChiffon;#FFFACD;Lime;#00FF00;PaleTurquoise;#AFEEEE;LightBlue;#ADD8E6;NavajoWhite;#FFDEAD;MintCream;#F5FFFA;DarkGray;#A9A9A9;;
|
||||
PaleVioletRed;#DB7093;Violet;#EE82EE;IndianRed;#CD5C5C;OrangeRed;#FF4500;LightGoldenRodYellow;#FAFAD2;LimeGreen;#32CD32;Aquamarine;#7FFFD4;PowderBlue;#B0E0E6;Wheat;#F5DEB3;Azure;#F0FFFF;DimGray;#696969;;
|
||||
MediumVioletRed;#C71585;Fuchsia;#FF00FF;Crimson;#DC143C;;;PapayaWhip;#FFEFD5;PaleGreen;#98FB98;Turquoise;#40E0D0;LightSkyBlue;#87CEFA;BurlyWood;#DEB887;AliceBlue;#F0F8FF;Gray;#808080;;
|
||||
;;Magenta;#FF00FF;Red;#FF0000;;;Moccasin;#FFE4B5;LightGreen;#90EE90;MediumTurquoise;#48D1CC;SkyBlue;#87CEEB;Tan;#D2B48C;GhostWhite;#F8F8FF;LightSlateGray;#778899;;
|
||||
;;MediumOrchid;#BA55D3;FireBrick;#B22222;;;PeachPuff;#FFDAB9;MediumSpringGreen;#00FA9A;DarkTurquoise;#00CED1;CornflowerBlue;#6495ED;RosyBrown;#BC8F8F;WhiteSmoke;#F5F5F5;SlateGray;#708090;;
|
||||
;;DarkOrchid;#9932CC;DarkRed;#8B0000;;;PaleGoldenRod;#EEE8AA;SpringGreen;#00FF7F;;;DeepSkyBlue;#00BFFF;SandyBrown;#F4A460;SeaShell;#FFF5EE;DarkSlateGray;#2F4F4F;;
|
||||
;;DarkViolet;#9400D3;;;;;Khaki;#F0E68C;MediumSeaGreen;#3CB371;;;DodgerBlue;#1E90FF;GoldenRod;#DAA520;Beige;#F5F5DC;;;;
|
||||
;;BlueViolet;#8A2BE2;;;;;DarkKhaki;#BDB76B;SeaGreen;#2E8B57;;;RoyalBlue;#4169E1;DarkGoldenRod;#B8860B;OldLace;#FDF5E6;;;;
|
||||
;;DarkMagenta;#8B008B;;;;;;;ForestGreen;#228B22;;;Blue;#0000FF;Peru;#CD853F;FloralWhite;#FFFAF0;;;;
|
||||
;;Purple;#800080;;;;;;;Green;#008000;;;MediumBlue;#0000CD;Chocolate;#D2691E;Ivory;#FFFFF0;;;;
|
||||
;;MediumPurple;#9370DB;;;;;;;DarkGreen;#006400;;;DarkBlue;#00008B;Olive;#808000;AntiqueWhite;#FAEBD7;;;;
|
||||
;;MediumSlateBlue;#7B68EE;;;;;;;YellowGreen;#9ACD32;;;Navy;#000080;SaddleBrown;#8B4513;Linen;#FAF0E6;;;;
|
||||
;;SlateBlue;#6A5ACD;;;;;;;OliveDrab;#6B8E23;;;MidnightBlue;#191970;Sienna;#A0522D;LavenderBlush;#FFF0F5;;;;
|
||||
;;DarkSlateBlue;#483D8B;;;;;;;DarkOliveGreen;#556B2F;;;;;Brown;#A52A2A;MistyRose;#FFE4E1;;;;
|
||||
;;RebeccaPurple;#663399;;;;;;;MediumAquaMarine;#66CDAA;;;;;Maroon;#800000;;;;;;
|
||||
;;Indigo;#4B0082;;;;;;;DarkSeaGreen;#8FBC8F;;;;;;;;;;;;
|
||||
;;;;;;;;;;LightSeaGreen;#20B2AA;;;;;;;;;;;;
|
||||
;;;;;;;;;;DarkCyan;#008B8B;;;;;;;;;;;;
|
||||
;;;;;;;;;;Teal;#008080;;;;;;;;;;;;
|
||||
|
@ -1,6 +1,7 @@
|
||||
import ammico.faces as faces
|
||||
import ammico.text as text
|
||||
import ammico.objects as objects
|
||||
import ammico.colors as colors
|
||||
from ammico.utils import is_interactive
|
||||
import ammico.summary as summary
|
||||
import dash_renderjson
|
||||
@ -45,7 +46,7 @@ class AnalysisExplorer:
|
||||
"base0F": "#cc6633",
|
||||
}
|
||||
|
||||
# Setup the layout
|
||||
# Setup the layout
|
||||
app_layout = html.Div(
|
||||
[
|
||||
# Top
|
||||
@ -197,7 +198,9 @@ class AnalysisExplorer:
|
||||
else:
|
||||
return None
|
||||
|
||||
def _right_output_analysis(self, all_options: dict, current_value: str) -> dict:
|
||||
def _right_output_analysis(
|
||||
self, image, all_options: dict, current_value: str
|
||||
) -> dict:
|
||||
"""Callback function to perform analysis on the selected image and return the output.
|
||||
|
||||
Args:
|
||||
@ -212,6 +215,7 @@ class AnalysisExplorer:
|
||||
"text-on-image": text.TextDetector,
|
||||
"objects": objects.ObjectDetector,
|
||||
"summary": summary.SummaryDetector,
|
||||
"colors": colors.ColorDetector,
|
||||
}
|
||||
|
||||
# Get image ID from dropdown value, which is the filepath
|
||||
|
||||
195
ammico/notebooks/colors_analysis.ipynb
Обычный файл
195
ammico/notebooks/colors_analysis.ipynb
Обычный файл
@ -0,0 +1,195 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Color analysis of pictures\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"This notebook shows primary color analysis of color image using K-Means algorithm.\n",
|
||||
"The output are N primary colors and their corresponding percentage.\n",
|
||||
"\n",
|
||||
"The first cell is only run on google colab and installs the [ammico](https://github.com/ssciwr/AMMICO) package.\n",
|
||||
"\n",
|
||||
"After that, we can import `ammico` and read in the files given a folder path."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# if running on google colab\n",
|
||||
"# flake8-noqa-cell\n",
|
||||
"import os\n",
|
||||
"\n",
|
||||
"if \"google.colab\" in str(get_ipython()):\n",
|
||||
" # update python version\n",
|
||||
" # install setuptools\n",
|
||||
" # %pip install setuptools==61 -qqq\n",
|
||||
" # install ammico\n",
|
||||
" %pip install git+https://github.com/ssciwr/ammico.git -qqq\n",
|
||||
" # mount google drive for data and API key\n",
|
||||
" from google.colab import drive\n",
|
||||
"\n",
|
||||
" drive.mount(\"/content/drive\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import ammico\n",
|
||||
"from ammico import utils as mutils\n",
|
||||
"from ammico import display as mdisplay\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"We select a subset of image files to try the color analysis on, see the `limit` keyword. The `find_files` function finds image files within a given directory:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Here you need to provide the path to your google drive folder\n",
|
||||
"# or local folder containing the images\n",
|
||||
"images = mutils.find_files(\n",
|
||||
" path=\"/content/drive/MyDrive/misinformation-data/\",\n",
|
||||
" limit=10,\n",
|
||||
")\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"We need to initialize the main dictionary that contains all information for the images and is updated through each subsequent analysis:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"mydict = mutils.initialize_dict(images)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"To check the analysis, you can inspect the analyzed elements here. Loading the results takes a moment, so please be patient. If you are sure of what you are doing, you can skip this and directly export a csv file in the step below.\n",
|
||||
"Here, we display the color detection results provided by `colorgram` and `colour` libraries. Click on the tabs to see the results in the right sidebar. You may need to increment the `port` number if you are already running several notebook instances on the same server."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"analysis_explorer = mdisplay.AnalysisExplorer(mydict, identify=\"colors\")\n",
|
||||
"analysis_explorer.run_server(port = 8057)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Instead of inspecting each of the images, you can also directly carry out the analysis and export the result into a csv. This may take a while depending on how many images you have loaded."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"for key in mydict.keys():\n",
|
||||
" mydict[key] = ammico.colors.ColorDetector(mydict[key]).analyse_image()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"These steps are required to convert the dictionary of dictionarys into a dictionary with lists, that can be converted into a pandas dataframe and exported to a csv file."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"outdict = mutils.append_data_to_dict(mydict)\n",
|
||||
"df = mutils.dump_df(outdict)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Check the dataframe:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"df.head(10)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Write the csv file - here you should provide a file path and file name for the csv file to be written."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"df.to_csv(\"/content/drive/MyDrive/misinformation-data/data_out.csv\")"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.9.16"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
@ -1,152 +0,0 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"This notebook shows primary color analysis of color image using K-Means algorithm.\n",
|
||||
"The output are N primary colors and their corresponding percentage."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from sklearn.cluster import KMeans\n",
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"import cv2\n",
|
||||
"import numpy as np\n",
|
||||
"import requests"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def centroid_histogram(clt):\n",
|
||||
" # grab the number of different clusters and create a histogram\n",
|
||||
" # based on the number of pixels assigned to each cluster\n",
|
||||
" numLabels = np.arange(0, len(np.unique(clt.labels_)) + 1)\n",
|
||||
" (hist, _) = np.histogram(clt.labels_, bins=numLabels)\n",
|
||||
"\n",
|
||||
" # normalize the histogram, such that it sums to one\n",
|
||||
" hist = hist.astype(\"float\")\n",
|
||||
" hist /= hist.sum()\n",
|
||||
"\n",
|
||||
" # return the histogram\n",
|
||||
" return hist\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def plot_colors(hist, centroids):\n",
|
||||
" # initialize the bar chart representing the relative frequency\n",
|
||||
" # of each of the colors\n",
|
||||
" bar = np.zeros((50, 300, 3), dtype=\"uint8\")\n",
|
||||
" startX = 0\n",
|
||||
" # loop over the percentage of each cluster and the color of\n",
|
||||
" # each cluster\n",
|
||||
" for percent, color in zip(hist, centroids):\n",
|
||||
" # plot the relative percentage of each cluster\n",
|
||||
" endX = startX + (percent * 300)\n",
|
||||
" cv2.rectangle(\n",
|
||||
" bar, (int(startX), 0), (int(endX), 50), color.astype(\"uint8\").tolist(), -1\n",
|
||||
" )\n",
|
||||
" startX = endX\n",
|
||||
"\n",
|
||||
" # return the bar chart\n",
|
||||
" return bar"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# load the image and convert it from BGR to RGB so that\n",
|
||||
"# we can dispaly it with matplotlib\n",
|
||||
"# image_path = './data/blue.jpg'\n",
|
||||
"# image = cv2.imread(image_path)\n",
|
||||
"\n",
|
||||
"file = requests.get(\n",
|
||||
" \"https://heibox.uni-heidelberg.de/thumbnail/537e6da0a8b44069bc96/1024/images/100361_asm.png\"\n",
|
||||
")\n",
|
||||
"image = cv2.imdecode(np.fromstring(file.content, np.uint8), 1)\n",
|
||||
"\n",
|
||||
"# BGR-->RGB cv to matplotlib show\n",
|
||||
"image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n",
|
||||
"\n",
|
||||
"# show our image\n",
|
||||
"plt.figure()\n",
|
||||
"plt.axis(\"off\")\n",
|
||||
"plt.imshow(image)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# reshape the image to be a list of pixels\n",
|
||||
"image = image.reshape((image.shape[0] * image.shape[1], 3))\n",
|
||||
"\n",
|
||||
"# cluster the pixel intensities\n",
|
||||
"clt = KMeans(n_clusters=8)\n",
|
||||
"clt.fit(image)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# build a histogram of clusters and then create a figure\n",
|
||||
"# representing the number of pixels labeled to each color\n",
|
||||
"hist = centroid_histogram(clt)\n",
|
||||
"bar = plot_colors(hist, clt.cluster_centers_)\n",
|
||||
"\n",
|
||||
"# show our color bart\n",
|
||||
"plt.figure()\n",
|
||||
"plt.axis(\"off\")\n",
|
||||
"plt.imshow(bar)\n",
|
||||
"plt.show()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"for percent, color in zip(hist, clt.cluster_centers_):\n",
|
||||
" print(\"color:\", color, \" percentage:\", percent)"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.7.3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
55
ammico/test/test_colors.py
Обычный файл
55
ammico/test/test_colors.py
Обычный файл
@ -0,0 +1,55 @@
|
||||
from ammico.colors import ColorDetector
|
||||
import pytest
|
||||
|
||||
|
||||
def test_set_keys():
|
||||
colors = {
|
||||
"red": 0,
|
||||
"green": 0,
|
||||
"blue": 0,
|
||||
"yellow": 0,
|
||||
"cyan": 0,
|
||||
"orange": 0,
|
||||
"purple": 0,
|
||||
"pink": 0,
|
||||
"brown": 0,
|
||||
"grey": 0,
|
||||
"white": 0,
|
||||
"black": 0,
|
||||
}
|
||||
cd = ColorDetector({})
|
||||
|
||||
for color_key, value in colors.items():
|
||||
assert cd.subdict[color_key] == value
|
||||
|
||||
|
||||
def test_rgb2name(get_path):
|
||||
cd = ColorDetector({})
|
||||
|
||||
assert cd.rgb2name([0, 0, 0]) == "black"
|
||||
assert cd.rgb2name([255, 255, 255]) == "white"
|
||||
assert cd.rgb2name([205, 133, 63]) == "brown"
|
||||
|
||||
assert cd.rgb2name([255, 255, 255], merge_color=False) == "white"
|
||||
assert cd.rgb2name([0, 0, 0], merge_color=False) == "black"
|
||||
assert cd.rgb2name([205, 133, 63], merge_color=False) == "peru"
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
cd.rgb2name([1, 2])
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
cd.rgb2name([1, 2, 3, 4])
|
||||
|
||||
|
||||
def test_analyze_images(get_path):
|
||||
mydict_1 = {
|
||||
"filename": get_path + "IMG_2809.png",
|
||||
}
|
||||
|
||||
test1 = ColorDetector(mydict_1, delta_e_method="CIE 2000").analyse_image()
|
||||
assert test1["red"] == 0.0
|
||||
assert round(test1["green"], 2) == 0.62
|
||||
|
||||
test2 = ColorDetector(mydict_1).analyse_image()
|
||||
assert test2["red"] == 0.0
|
||||
assert test2["green"] == 0.05
|
||||
@ -49,8 +49,8 @@ def test_AnalysisExplorer(get_path):
|
||||
|
||||
assert analysis_explorer_objects.update_picture(None) is None
|
||||
|
||||
analysis_explorer_faces._right_output_analysis(all_options_dict, path_img_1)
|
||||
analysis_explorer_objects._right_output_analysis(all_options_dict, path_img_2)
|
||||
analysis_explorer_faces._right_output_analysis(None, all_options_dict, path_img_1)
|
||||
analysis_explorer_objects._right_output_analysis(None, all_options_dict, path_img_2)
|
||||
|
||||
with pytest.raises(EnvironmentError):
|
||||
analysis_explorer_faces.run_server(port=8050)
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import glob
|
||||
import os
|
||||
from pandas import DataFrame
|
||||
from pandas import DataFrame, read_csv
|
||||
import pooch
|
||||
|
||||
|
||||
@ -107,3 +107,17 @@ def is_interactive():
|
||||
import __main__ as main
|
||||
|
||||
return not hasattr(main, "__file__")
|
||||
|
||||
|
||||
def get_color_table():
|
||||
df_colors = read_csv(
|
||||
os.path.join(os.path.dirname(__file__), "data", "Color_tables.csv"),
|
||||
delimiter=";",
|
||||
dtype=str,
|
||||
encoding="UTF-8",
|
||||
header=[0, 1],
|
||||
)
|
||||
return {
|
||||
col_key: df_colors[col_key].dropna().to_dict("list")
|
||||
for col_key in df_colors.columns.levels[0]
|
||||
}
|
||||
|
||||
@ -29,6 +29,14 @@ faces module
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
color_analysis module
|
||||
---------------------
|
||||
|
||||
.. automodule:: color_analysis
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
objects module
|
||||
--------------
|
||||
|
||||
@ -15,6 +15,7 @@ Welcome to AMMICO's documentation!
|
||||
notebooks/Example text
|
||||
notebooks/Example summary
|
||||
notebooks/Example multimodal
|
||||
notebooks/Example colors
|
||||
notebooks/Example objects
|
||||
notebooks/Example cropposts
|
||||
modules
|
||||
|
||||
195
docs/source/notebooks/Example colors.ipynb
Обычный файл
195
docs/source/notebooks/Example colors.ipynb
Обычный файл
@ -0,0 +1,195 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Color analysis of pictures\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"This notebook shows primary color analysis of color image using K-Means algorithm.\n",
|
||||
"The output are N primary colors and their corresponding percentage.\n",
|
||||
"\n",
|
||||
"The first cell is only run on google colab and installs the [ammico](https://github.com/ssciwr/AMMICO) package.\n",
|
||||
"\n",
|
||||
"After that, we can import `ammico` and read in the files given a folder path."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# if running on google colab\n",
|
||||
"# flake8-noqa-cell\n",
|
||||
"import os\n",
|
||||
"\n",
|
||||
"if \"google.colab\" in str(get_ipython()):\n",
|
||||
" # update python version\n",
|
||||
" # install setuptools\n",
|
||||
" # %pip install setuptools==61 -qqq\n",
|
||||
" # install ammico\n",
|
||||
" %pip install git+https://github.com/ssciwr/ammico.git -qqq\n",
|
||||
" # mount google drive for data and API key\n",
|
||||
" from google.colab import drive\n",
|
||||
"\n",
|
||||
" drive.mount(\"/content/drive\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import ammico\n",
|
||||
"from ammico import utils as mutils\n",
|
||||
"from ammico import display as mdisplay\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"We select a subset of image files to try the color analysis on, see the `limit` keyword. The `find_files` function finds image files within a given directory:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Here you need to provide the path to your google drive folder\n",
|
||||
"# or local folder containing the images\n",
|
||||
"images = mutils.find_files(\n",
|
||||
" path=\"/content/drive/MyDrive/misinformation-data/\",\n",
|
||||
" limit=10,\n",
|
||||
")\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"We need to initialize the main dictionary that contains all information for the images and is updated through each subsequent analysis:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"mydict = mutils.initialize_dict(images)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"To check the analysis, you can inspect the analyzed elements here. Loading the results takes a moment, so please be patient. If you are sure of what you are doing, you can skip this and directly export a csv file in the step below.\n",
|
||||
"Here, we display the color detection results provided by `colorgram` and `colour` libraries. Click on the tabs to see the results in the right sidebar. You may need to increment the `port` number if you are already running several notebook instances on the same server."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"analysis_explorer = mdisplay.AnalysisExplorer(mydict, identify=\"colors\")\n",
|
||||
"analysis_explorer.run_server(port = 8057)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Instead of inspecting each of the images, you can also directly carry out the analysis and export the result into a csv. This may take a while depending on how many images you have loaded."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"for key in mydict.keys():\n",
|
||||
" mydict[key] = ammico.colors.ColorDetector(mydict[key]).analyse_image()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"These steps are required to convert the dictionary of dictionarys into a dictionary with lists, that can be converted into a pandas dataframe and exported to a csv file."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"outdict = mutils.append_data_to_dict(mydict)\n",
|
||||
"df = mutils.dump_df(outdict)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Check the dataframe:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"df.head(10)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Write the csv file - here you should provide a file path and file name for the csv file to be written."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"df.to_csv(\"/content/drive/MyDrive/misinformation-data/data_out.csv\")"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.9.16"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
@ -49,14 +49,29 @@ dependencies = [
|
||||
"tensorflow",
|
||||
"torch",
|
||||
"transformers",
|
||||
"google-cloud-vision",
|
||||
"setuptools",
|
||||
"opencv-contrib-python",
|
||||
"dash",
|
||||
"jupyter_dash",
|
||||
"dash_renderjson",
|
||||
"colorgram.py",
|
||||
"webcolors",
|
||||
"colour-science",
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
ammico_prefetch_models = "ammico.utils:ammico_prefetch_models"
|
||||
|
||||
[project.urls]
|
||||
homepage = "https://github.com/ssciwr/AMMICO" # FIXME not shown by pip
|
||||
documentation = "https://ssciwr.github.io/AMMICO/build/html/index.html"
|
||||
|
||||
[tool.setuptools]
|
||||
packages = ["ammico"]
|
||||
|
||||
[tool.setuptools.package-data]
|
||||
# Include any png files found in the "data" subdirectory of "ammico"
|
||||
"ammico.data" = ["*.png"]
|
||||
"ammico.data" = ["*.png"]
|
||||
mypkg = [ "*.csv"]
|
||||
|
||||
|
||||
Загрузка…
x
Ссылка в новой задаче
Block a user