Refactored and modified the project structure
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
This commit is contained in:
parent
6ae51c648b
commit
6b54d44959
23 changed files with 383 additions and 76 deletions
|
@ -2,6 +2,11 @@ pipeline:
|
||||||
flake8:
|
flake8:
|
||||||
image: python:3.8
|
image: python:3.8
|
||||||
commands:
|
commands:
|
||||||
- pip install flake8
|
- python3.8 -m pip install flake8
|
||||||
- flake8 src/
|
- flake8 src/
|
||||||
|
mypy:
|
||||||
|
image: python:3.8
|
||||||
|
commands:
|
||||||
|
- python3.8 -m pip install mypy
|
||||||
|
- mypy src/
|
||||||
+branches: dev
|
+branches: dev
|
13
docker-compose.yaml
Normal file
13
docker-compose.yaml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
version: "3.3"
|
||||||
|
|
||||||
|
services:
|
||||||
|
autophotographer:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile.cpu
|
||||||
|
image: noble/autophotographer
|
||||||
|
volumes:
|
||||||
|
# Source of project
|
||||||
|
- ./src:/src
|
||||||
|
# Location of dataset
|
||||||
|
- $HOME/Documents/Datasets:/datasets
|
5
environment.yml
Normal file
5
environment.yml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
name: autophotographer
|
||||||
|
dependencies:
|
||||||
|
- numpy
|
||||||
|
- pandas
|
||||||
|
- python=3.8
|
160
src/.gitignore
vendored
Normal file
160
src/.gitignore
vendored
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py,cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
cover/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
db.sqlite3-journal
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
.pybuilder/
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
# For a library or package, you might want to ignore these files since the code is
|
||||||
|
# intended to run in multiple environments; otherwise, check them in:
|
||||||
|
# .python-version
|
||||||
|
|
||||||
|
# pipenv
|
||||||
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||||
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||||
|
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||||
|
# install all needed dependencies.
|
||||||
|
#Pipfile.lock
|
||||||
|
|
||||||
|
# poetry
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||||
|
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||||
|
# commonly ignored for libraries.
|
||||||
|
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||||
|
#poetry.lock
|
||||||
|
|
||||||
|
# pdm
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||||
|
#pdm.lock
|
||||||
|
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||||
|
# in version control.
|
||||||
|
# https://pdm.fming.dev/#use-with-ide
|
||||||
|
.pdm.toml
|
||||||
|
|
||||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Celery stuff
|
||||||
|
celerybeat-schedule
|
||||||
|
celerybeat.pid
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
||||||
|
|
||||||
|
# pytype static type analyzer
|
||||||
|
.pytype/
|
||||||
|
|
||||||
|
# Cython debug symbols
|
||||||
|
cython_debug/
|
||||||
|
|
||||||
|
# PyCharm
|
||||||
|
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||||
|
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||||
|
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||||
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
|
#.idea/
|
|
@ -1,27 +1,40 @@
|
||||||
|
# IMPORTS
|
||||||
|
# import from
|
||||||
|
from tqdm import tqdm
|
||||||
|
from skimage.exposure import is_low_contrast
|
||||||
|
from os.path import abspath
|
||||||
|
|
||||||
|
# import as
|
||||||
|
import pandas as pd
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
# imports
|
||||||
import cv2
|
import cv2
|
||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
from os.path import abspath
|
|
||||||
import pandas
|
|
||||||
import matplotlib.pyplot as plt
|
|
||||||
import numpy as np
|
|
||||||
from skimage.exposure import is_low_contrast
|
|
||||||
import yaml
|
import yaml
|
||||||
|
import math
|
||||||
|
|
||||||
# Import local packages
|
# local imports for filters
|
||||||
from focusdetection.focusdetection import fast_fourier
|
import filters.focusdetection.focusdetection as focusdetection
|
||||||
|
import filters.brightness.brightness as brightness
|
||||||
#import sys
|
|
||||||
#import pathlib
|
|
||||||
#import numpy
|
|
||||||
#import time
|
|
||||||
|
|
||||||
|
# GLOBAL VARIABLES
|
||||||
# accepted image formats
|
# accepted image formats
|
||||||
image_formats = (".jpg", ".jpeg", ".png")
|
image_formats = (".jpg", ".jpeg", ".png")
|
||||||
|
|
||||||
# accepted video formats
|
# accepted video formats
|
||||||
video_formats = (".mp4", ".mov", ".avi", ".flv", ".mkv")
|
video_formats = (".mp4", ".mov", ".avi", ".flv", ".mkv")
|
||||||
|
|
||||||
|
# default options
|
||||||
|
brightness_thresh = 0.35
|
||||||
|
focus_thresh = 0.35
|
||||||
|
filesize_thresh = 0.35
|
||||||
|
contrast_thresh = 0.35
|
||||||
|
ignore_video = False
|
||||||
|
|
||||||
|
# FUNCTIONS
|
||||||
# load config file
|
# load config file
|
||||||
def load_config(path=os.path.join(os.path.dirname(__file__), "./config.yml")):
|
def load_config(path=os.path.join(os.path.dirname(__file__), "./config.yml")):
|
||||||
abs_path = os.path.abspath(path)
|
abs_path = os.path.abspath(path)
|
||||||
|
@ -40,33 +53,50 @@ def load_config(path=os.path.join(os.path.dirname(__file__), "./config.yml")):
|
||||||
print("[ERRO] Path does not exist")
|
print("[ERRO] Path does not exist")
|
||||||
quit()
|
quit()
|
||||||
|
|
||||||
def filter_to_function(imagefilter, prettyName=False):
|
# load the correct filter function from filter name
|
||||||
if imageFilter == "brightness":
|
def filter_to_function(imagefilter: str, paths: list) -> list:
|
||||||
# filter_brightness()
|
if imageFilter == "brightness":
|
||||||
print("[INFO] Filtering based on brightness...")
|
paths = filter_brightness(paths, brightness_thresh)
|
||||||
elif imageFilter == "filesize":
|
print("[INFO] Filtering based on brightness...")
|
||||||
# filter_filesize()
|
elif imageFilter == "filesize":
|
||||||
print("[INFO] Filtering based on filesize...")
|
paths = filter_filesize(paths, filesize_thresh)
|
||||||
elif imageFilter == "contrast":
|
print("[INFO] Filtering based on filesize...")
|
||||||
# filter_contrast()
|
elif imageFilter == "contrast":
|
||||||
print("[INFO] Filtering based on contrast...")
|
paths = filter_contrast(paths, contrast_thresh)
|
||||||
elif imageFilter == "focus":
|
print("[INFO] Filtering based on contrast...")
|
||||||
# filter_focus()
|
elif imageFilter == "focus":
|
||||||
print("[INFO] Filtering based on focus...")
|
paths = filter_focus(paths, focus_thresh)
|
||||||
else:
|
print("[INFO] Filtering based on focus...")
|
||||||
print("[WARN] Filter not recognised. Ignoring...")
|
else:
|
||||||
|
print("[WARN] Filter not recognised. Ignoring...")
|
||||||
|
return paths
|
||||||
|
|
||||||
# filter paths by accepted file extensions
|
# filter paths by accepted file extensions
|
||||||
def filter_paths(paths):
|
def filter_paths(paths: list) -> list:
|
||||||
print("[INFO] Filtering paths by filetype...")
|
print("[INFO] Filtering paths by filetype...")
|
||||||
filtered_paths = []
|
filtered_paths = []
|
||||||
for path in paths:
|
|
||||||
if path.lower().endswith(video_formats + image_formats):
|
# if input location is a directory then fetch all files in that directory
|
||||||
filtered_paths.append(path)
|
if len(paths) == 1 and os.path.isdir(paths[0]):
|
||||||
|
list_dir = os.listdir(paths[0])
|
||||||
|
new_paths = []
|
||||||
|
for filename in list_dir:
|
||||||
|
new_paths.append(os.path.join(args["input"][0], filename))
|
||||||
|
paths = new_paths
|
||||||
|
|
||||||
|
# if ignore_video is set to true then filter out video files
|
||||||
|
if ignore_video:
|
||||||
|
for path in paths:
|
||||||
|
if path.lower().endswith(image_formats):
|
||||||
|
filtered_paths.append(path)
|
||||||
|
else:
|
||||||
|
for path in paths:
|
||||||
|
if path.lower().endswith(video_formats + image_formats):
|
||||||
|
filtered_paths.append(path)
|
||||||
return filtered_paths
|
return filtered_paths
|
||||||
|
|
||||||
# load frames from images
|
# load frames from images
|
||||||
def load_video(path):
|
def load_video(path: str) -> list:
|
||||||
print("[INFO] Loading video...")
|
print("[INFO] Loading video...")
|
||||||
stream = cv2.VideoCapture(path)
|
stream = cv2.VideoCapture(path)
|
||||||
frames = []
|
frames = []
|
||||||
|
@ -78,8 +108,9 @@ def load_video(path):
|
||||||
return frames
|
return frames
|
||||||
|
|
||||||
# load images
|
# load images
|
||||||
def load_image(path):
|
# note although trivial, a method was created so the way in which a file is loaded can be easily changed
|
||||||
print("[INFO] Loading image...")
|
def load_image(path: str):
|
||||||
|
# print("[INFO] Loading image...")
|
||||||
image = cv2.imread(path)
|
image = cv2.imread(path)
|
||||||
return image
|
return image
|
||||||
|
|
||||||
|
@ -122,7 +153,7 @@ def load_files(paths):
|
||||||
return (images, videos)
|
return (images, videos)
|
||||||
|
|
||||||
# filter images based on filesize
|
# filter images based on filesize
|
||||||
def filter_filesize(paths):
|
def filter_filesize(paths, thresh=0.35):
|
||||||
print("[INFO] Filtering by filesize...")
|
print("[INFO] Filtering by filesize...")
|
||||||
filesizes = []
|
filesizes = []
|
||||||
filtered_paths = []
|
filtered_paths = []
|
||||||
|
@ -131,7 +162,7 @@ def filter_filesize(paths):
|
||||||
filesize = os.path.getsize(path)
|
filesize = os.path.getsize(path)
|
||||||
filesizes.append(filesize)
|
filesizes.append(filesize)
|
||||||
filesize_avg = sum(filesizes)/len(filesizes)
|
filesize_avg = sum(filesizes)/len(filesizes)
|
||||||
filesize_std = pandas.Series(filesizes).std(ddof=0)
|
filesize_std = pd.Series(filesizes).std(ddof=0)
|
||||||
filesize_min = min(filesizes)
|
filesize_min = min(filesizes)
|
||||||
filesize_max = max(filesizes)
|
filesize_max = max(filesizes)
|
||||||
filesize_filter = filesize_avg - filesize_std
|
filesize_filter = filesize_avg - filesize_std
|
||||||
|
@ -157,10 +188,11 @@ def plot_filesizes(paths):
|
||||||
fig = plt.figure(figsize =(10, 7))
|
fig = plt.figure(figsize =(10, 7))
|
||||||
plt.boxplot(data)
|
plt.boxplot(data)
|
||||||
plt.show()
|
plt.show()
|
||||||
|
return plt
|
||||||
|
|
||||||
# resize image and turn to greyscale
|
# resize image and turn to greyscale
|
||||||
def process_image(path, width):
|
def process_image(path, width):
|
||||||
print("[INFO] Processing image...")
|
# print("[INFO] Processing image...")
|
||||||
image = cv2.imread(path)
|
image = cv2.imread(path)
|
||||||
height = int(image.shape[0] * (width / image.shape[0]))
|
height = int(image.shape[0] * (width / image.shape[0]))
|
||||||
image = cv2.resize(image, (width, height))
|
image = cv2.resize(image, (width, height))
|
||||||
|
@ -169,38 +201,63 @@ def process_image(path, width):
|
||||||
|
|
||||||
# filter images based on contrast
|
# filter images based on contrast
|
||||||
def filter_contrast(paths, thresh=0.35):
|
def filter_contrast(paths, thresh=0.35):
|
||||||
print("[INFO] Filtering by contrast...")
|
# print("[INFO] Filtering by contrast...")
|
||||||
filtered_paths = []
|
filtered_paths = []
|
||||||
for path in paths:
|
for path in tqdm(paths, desc="Filtering contrast"):
|
||||||
if path.lower().endswith(video_formats):
|
if path.lower().endswith(video_formats):
|
||||||
continue
|
continue
|
||||||
print(path)
|
# print(path)
|
||||||
image = process_image(path, 500)
|
image = process_image(path, 500)
|
||||||
if is_low_contrast(image, thresh):
|
if is_low_contrast(image, thresh):
|
||||||
print("[INFO] Low contrast")
|
# print("[INFO] Low contrast")
|
||||||
|
continue
|
||||||
else:
|
else:
|
||||||
print("[INFO] High contrast")
|
# print("[INFO] High contrast")
|
||||||
filtered_paths.append(path)
|
filtered_paths.append(path)
|
||||||
return filtered_paths
|
return filtered_paths
|
||||||
|
|
||||||
# filter images based on brightness
|
# filter images based on brightness
|
||||||
def filter_brightness(paths):
|
def filter_brightness(paths, thresh=0.35):
|
||||||
print("[INFO] Filtering by brightness...")
|
filtered_paths = []
|
||||||
|
for path in tqdm(paths, desc="Filtering brightness"):
|
||||||
|
image = load_image(path)
|
||||||
|
# width = 20
|
||||||
|
# height = int(image.shape[0] * (width / image.shape[0]))
|
||||||
|
# image = cv2.resize(image, (width, height))
|
||||||
|
# L, A, B = cv2.split(cv2.cvtColor(image, cv2.COLOR_BGR2LAB))
|
||||||
|
# L = L/np.max(L)
|
||||||
|
luminance = brightness.get_luminance_value(image)
|
||||||
|
if luminance > thresh:
|
||||||
|
filtered_paths.append(path)
|
||||||
|
return filtered_paths
|
||||||
|
|
||||||
|
|
||||||
|
# print("[INFO] Filtering by brightness...")
|
||||||
|
|
||||||
|
def filter_brightness_dataframe(paths):
|
||||||
|
df = pd.DataFrame(paths, columns =['path'])
|
||||||
|
for path in tqdm(paths, desc="Filtering brightness"):
|
||||||
|
image = load_image(path)
|
||||||
|
luminance = brightness.get_luminance_value(image)
|
||||||
|
row = (df.index[df["path"] == path])[0]
|
||||||
|
df.at[row, "brightness"] = luminance
|
||||||
|
return df
|
||||||
|
|
||||||
# filter images based on focus/blurriness
|
# filter images based on focus/blurriness
|
||||||
def filter_focus(paths):
|
def filter_focus(paths, thresh=0.35):
|
||||||
print("[INFO] Filtering by focus/blurriness...")
|
print("[INFO] Filtering by focus/blurriness...")
|
||||||
filtered_paths = []
|
filtered_paths = []
|
||||||
# read images in greyscale
|
# read images in greyscale
|
||||||
for path in paths:
|
for path in tqdm(paths, desc="Filtering focus"):
|
||||||
if path.lower().endswith(video_formats):
|
if path.lower().endswith(video_formats):
|
||||||
continue
|
continue
|
||||||
print(path)
|
# print(path)
|
||||||
image = process_image(path, 500)
|
image = process_image(path, 500)
|
||||||
(mean, blurry) = fast_fourier(image, size=60, thresh=30)
|
(mean, blurry) = focusdetection.fast_fourier(image, size=60, thresh=30)
|
||||||
blurStats = "Blurry ({:.4f})" if blurry else "Not blurry ({:.4f})"
|
blurStats = "Blurry ({:.4f})" if blurry else "Not blurry ({:.4f})"
|
||||||
if blurry:
|
if blurry:
|
||||||
print(("[INFO] {}: " + blurStats).format(path, mean))
|
# print(("[INFO] {}: " + blurStats).format(path, mean))
|
||||||
|
continue
|
||||||
else:
|
else:
|
||||||
filtered_paths.append(path)
|
filtered_paths.append(path)
|
||||||
return filtered_paths
|
return filtered_paths
|
||||||
|
@ -209,31 +266,81 @@ def filter_focus(paths):
|
||||||
def rank_images():
|
def rank_images():
|
||||||
print("[INFO] Ranking images using machine learning...")
|
print("[INFO] Ranking images using machine learning...")
|
||||||
|
|
||||||
# parse commande line arguments
|
def display_images(paths, location):
|
||||||
|
# create figure
|
||||||
|
|
||||||
|
row = math.ceil(math.sqrt(len(paths)))
|
||||||
|
width = 100
|
||||||
|
size = width * row
|
||||||
|
fig = plt.figure(figsize=(50, 50))
|
||||||
|
|
||||||
|
index = 1
|
||||||
|
for path in tqdm(paths):
|
||||||
|
image = cv2.imread(path)
|
||||||
|
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
|
||||||
|
height = int(image.shape[0] * (width / image.shape[0]))
|
||||||
|
image = cv2.resize(image, (width, height))
|
||||||
|
fig.add_subplot(row, row, index)
|
||||||
|
plt.imshow(image)
|
||||||
|
plt.axis('off')
|
||||||
|
filename = os.path.split(path)[1]
|
||||||
|
print(filename)
|
||||||
|
plt.title(filename)
|
||||||
|
index += 1
|
||||||
|
|
||||||
|
plt.savefig(location)
|
||||||
|
|
||||||
|
# parse command line arguments
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument("-i", "--input", type=os.path.abspath, required=True, nargs="+",
|
parser.add_argument("-i", "--input", type=os.path.abspath, required=True, nargs="+",
|
||||||
help="path to video or image folder")
|
help="path to video or image folder")
|
||||||
parser.add_argument("-c", "--config", type=os.path.abspath, help="path to config file")
|
parser.add_argument("-c", "--config", type=os.path.abspath, help="path to config file")
|
||||||
args = vars(parser.parse_args())
|
args = vars(parser.parse_args())
|
||||||
|
|
||||||
paths = filter_paths(args["input"])
|
|
||||||
|
|
||||||
# load in config file
|
# load in config file
|
||||||
if args["config"] is not None:
|
if args["config"] is not None:
|
||||||
autophotoConf = load_config(args["config"])
|
autophotoConf = load_config(args["config"])
|
||||||
else:
|
else:
|
||||||
autophotoConf = load_config()
|
autophotoConf = load_config()
|
||||||
|
|
||||||
# Order and selection of operations from config file
|
# Load values for options
|
||||||
for imageFilter in autophotoConf["filters"]:
|
if autophotoConf["brightness_options"]["threshold"] is not None:
|
||||||
n_of_images_before = len(paths)
|
brightness_thresh = autophotoConf["brightness_options"]["threshold"]
|
||||||
filter_to_function(imageFilter)
|
if autophotoConf["focus_options"]["threshold"] is not None:
|
||||||
n_of_images_after = len(paths)
|
focus_thresh = autophotoConf["focus_options"]["threshold"]
|
||||||
|
if autophotoConf["contrast_options"]["threshold"] is not None:
|
||||||
|
contrast_thresh = autophotoConf["contrast_options"]["threshold"]
|
||||||
|
if autophotoConf["filesize_options"]["threshold"] is not None:
|
||||||
|
filesize_thresh = autophotoConf["filesize_options"]["threshold"]
|
||||||
|
if autophotoConf["ignore_video"] is not None:
|
||||||
|
ignore_video = autophotoConf["ignore_video"]
|
||||||
|
|
||||||
# calculate set difference after filtering
|
paths = filter_paths(args["input"])
|
||||||
diff = n_of_images_before - n_of_images_after
|
print("[INFO] Loaded {} objects.".format(len(paths)))
|
||||||
print("[INFO] Filtered {}/{} images via {} filtering.".format(
|
prior_paths = []
|
||||||
n_of_images_after, n_of_images_before, imageFilter))
|
path_diff = []
|
||||||
|
|
||||||
|
# Order and selection of operations from config file
|
||||||
|
if autophotoConf["filters"] is not None:
|
||||||
|
|
||||||
|
# iterate over all chosen filters
|
||||||
|
for imageFilter in autophotoConf["filters"]:
|
||||||
|
prior_paths = paths
|
||||||
|
|
||||||
|
# run given filter
|
||||||
|
paths = filter_to_function(imageFilter, paths)
|
||||||
|
|
||||||
|
path_diff = list(set(paths) - set(prior_paths)) + list(set(prior_paths) - set(paths))
|
||||||
|
diff = len(prior_paths) - len(paths)
|
||||||
|
# filename = "/src/fig" + "-" + str(imageFilter) + ".png"
|
||||||
|
# display_images(path_diff, filename)
|
||||||
|
|
||||||
|
# calculate set difference after filtering
|
||||||
|
if diff == 0:
|
||||||
|
print("[INFO] No images were filtered.")
|
||||||
|
else:
|
||||||
|
print("[INFO] Filtered {}/{} images via {} filtering.".format(
|
||||||
|
len(paths), len(prior_paths), imageFilter))
|
||||||
|
|
||||||
if autophotoConf["CNNrank"]:
|
if autophotoConf["CNNrank"]:
|
||||||
print("[INFO] Running CNN ranking...")
|
print("[INFO] Running CNN ranking...")
|
Can't render this file because it is too large.
|
|
@ -22,12 +22,14 @@ datasetDir = "/datasets/"
|
||||||
script_directory = os.path.dirname(__file__)
|
script_directory = os.path.dirname(__file__)
|
||||||
projectRoot = abspath(os.path.join(script_directory, "../.."))
|
projectRoot = abspath(os.path.join(script_directory, "../.."))
|
||||||
#projectRoot = "/src/"
|
#projectRoot = "/src/"
|
||||||
print(projectRoot)
|
# tensorImagesPath = os.path.join(projectRoot, "src/autophotographer/tensorImages.pt")
|
||||||
tensorImagesPath = os.path.join(projectRoot, "src/autophotographer/tensorImages.pt")
|
# tensorRatingsPath = os.path.join(projectRoot, "src/autophotographer/tensorRatings.pt")
|
||||||
tensorRatingsPath = os.path.join(projectRoot, "src/autophotographer/tensorRatings.pt")
|
# tensorArrayPath = os.path.join(projectRoot, "src/autophotographer/tensorArray.pt")
|
||||||
tensorArrayPath = os.path.join(projectRoot, "src/autophotographer/tensorArray.pt")
|
tensorImagesPath = os.path.join(script_directory, "tensorImages.pt")
|
||||||
|
tensorRatingsPath = os.path.join(script_directory, "tensorRatings.pt")
|
||||||
|
tensorArrayPath = os.path.join(script_directory, "tensorArray.pt")
|
||||||
filePathRatings = os.path.join(projectRoot, "data/ratings.txt")
|
filePathRatings = os.path.join(projectRoot, "data/ratings.txt")
|
||||||
dataframePath = os.path.join(projectRoot, "src/autophotographer/dataframe.csv")
|
dataframePath = os.path.join(script_directory, "dataframe.csv")
|
||||||
|
|
||||||
if not datasetDir == "":
|
if not datasetDir == "":
|
||||||
filePathStyle = datasetDir + "AVA/style_image_lists/test.multilab"
|
filePathStyle = datasetDir + "AVA/style_image_lists/test.multilab"
|
|
@ -1,7 +1,8 @@
|
||||||
---
|
---
|
||||||
# Config file for autophotographer
|
# Configuration file for the autophographer tool
|
||||||
|
|
||||||
# List of filters to apply in order
|
# List of filters to apply in order
|
||||||
|
# Note: Possible filters include: brightness, filesize, contrast, focus
|
||||||
filters:
|
filters:
|
||||||
- brightness
|
- brightness
|
||||||
- filesize
|
- filesize
|
||||||
|
@ -9,21 +10,25 @@ filters:
|
||||||
- focus
|
- focus
|
||||||
|
|
||||||
# Whether or not to apply CNN ranking
|
# Whether or not to apply CNN ranking
|
||||||
CNNrank: True
|
CNNrank: False
|
||||||
|
|
||||||
# Options for focus filter
|
# Ignore video files and don't bother processing them into frames
|
||||||
|
# Note: Useful if directory contains original video and indivual frames from video (prevents processing the same frames more than once)
|
||||||
|
ignore_video: True
|
||||||
|
|
||||||
|
# Options for brightness filter
|
||||||
brightness_options:
|
brightness_options:
|
||||||
threshold: 0.35
|
threshold: 0.25
|
||||||
|
|
||||||
# Options for focus filter
|
# Options for filesize filter
|
||||||
filesize_options:
|
filesize_options:
|
||||||
threshold: 0.35
|
threshold: 0.35
|
||||||
|
|
||||||
# Options for focus filter
|
# Options for contrast filter
|
||||||
contrast_options:
|
contrast_options:
|
||||||
threshold: 0.35
|
threshold: 0.35
|
||||||
|
|
||||||
# Options for focus filter
|
# Options for focus filter
|
||||||
focus_options:
|
focus_options:
|
||||||
threshold: 0.35
|
threshold: 0.5
|
||||||
...
|
...
|
10
src/filters/brightness/brightness.py
Normal file
10
src/filters/brightness/brightness.py
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import numpy as np
|
||||||
|
import cv2
|
||||||
|
|
||||||
|
def get_luminance_value(image):
|
||||||
|
width = 20
|
||||||
|
height = int(image.shape[0] * (width / image.shape[0]))
|
||||||
|
image = cv2.resize(image, (width, height))
|
||||||
|
L, A, B = cv2.split(cv2.cvtColor(image, cv2.COLOR_BGR2LAB))
|
||||||
|
L = L/np.max(L)
|
||||||
|
return np.mean(L)
|
0
src/filters/contrast/__init__.py
Normal file
0
src/filters/contrast/__init__.py
Normal file
0
src/filters/filesize/__init__.py
Normal file
0
src/filters/filesize/__init__.py
Normal file
0
src/filters/focusdetection/__init__.py
Normal file
0
src/filters/focusdetection/__init__.py
Normal file
|
@ -1,8 +1,8 @@
|
||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
from os.path import abspath
|
from os.path import abspath
|
||||||
from autophotographer import config
|
from cnn import config
|
||||||
from autophotographer import dataset
|
from cnn import dataset
|
||||||
from torchvision import transforms
|
from torchvision import transforms
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
from torch import nn
|
from torch import nn
|
||||||
|
|
Reference in a new issue