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:
|
||||
image: python:3.8
|
||||
commands:
|
||||
- pip install flake8
|
||||
- python3.8 -m pip install flake8
|
||||
- flake8 src/
|
||||
mypy:
|
||||
image: python:3.8
|
||||
commands:
|
||||
- python3.8 -m pip install mypy
|
||||
- mypy src/
|
||||
+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 argparse
|
||||
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 math
|
||||
|
||||
# Import local packages
|
||||
from focusdetection.focusdetection import fast_fourier
|
||||
|
||||
#import sys
|
||||
#import pathlib
|
||||
#import numpy
|
||||
#import time
|
||||
# local imports for filters
|
||||
import filters.focusdetection.focusdetection as focusdetection
|
||||
import filters.brightness.brightness as brightness
|
||||
|
||||
# GLOBAL VARIABLES
|
||||
# accepted image formats
|
||||
image_formats = (".jpg", ".jpeg", ".png")
|
||||
|
||||
# accepted video formats
|
||||
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
|
||||
def load_config(path=os.path.join(os.path.dirname(__file__), "./config.yml")):
|
||||
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")
|
||||
quit()
|
||||
|
||||
def filter_to_function(imagefilter, prettyName=False):
|
||||
if imageFilter == "brightness":
|
||||
# filter_brightness()
|
||||
print("[INFO] Filtering based on brightness...")
|
||||
elif imageFilter == "filesize":
|
||||
# filter_filesize()
|
||||
print("[INFO] Filtering based on filesize...")
|
||||
elif imageFilter == "contrast":
|
||||
# filter_contrast()
|
||||
print("[INFO] Filtering based on contrast...")
|
||||
elif imageFilter == "focus":
|
||||
# filter_focus()
|
||||
print("[INFO] Filtering based on focus...")
|
||||
else:
|
||||
print("[WARN] Filter not recognised. Ignoring...")
|
||||
# load the correct filter function from filter name
|
||||
def filter_to_function(imagefilter: str, paths: list) -> list:
|
||||
if imageFilter == "brightness":
|
||||
paths = filter_brightness(paths, brightness_thresh)
|
||||
print("[INFO] Filtering based on brightness...")
|
||||
elif imageFilter == "filesize":
|
||||
paths = filter_filesize(paths, filesize_thresh)
|
||||
print("[INFO] Filtering based on filesize...")
|
||||
elif imageFilter == "contrast":
|
||||
paths = filter_contrast(paths, contrast_thresh)
|
||||
print("[INFO] Filtering based on contrast...")
|
||||
elif imageFilter == "focus":
|
||||
paths = filter_focus(paths, focus_thresh)
|
||||
print("[INFO] Filtering based on focus...")
|
||||
else:
|
||||
print("[WARN] Filter not recognised. Ignoring...")
|
||||
return paths
|
||||
|
||||
# filter paths by accepted file extensions
|
||||
def filter_paths(paths):
|
||||
def filter_paths(paths: list) -> list:
|
||||
print("[INFO] Filtering paths by filetype...")
|
||||
filtered_paths = []
|
||||
for path in paths:
|
||||
if path.lower().endswith(video_formats + image_formats):
|
||||
filtered_paths.append(path)
|
||||
|
||||
# if input location is a directory then fetch all files in that directory
|
||||
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
|
||||
|
||||
# load frames from images
|
||||
def load_video(path):
|
||||
def load_video(path: str) -> list:
|
||||
print("[INFO] Loading video...")
|
||||
stream = cv2.VideoCapture(path)
|
||||
frames = []
|
||||
|
@ -78,8 +108,9 @@ def load_video(path):
|
|||
return frames
|
||||
|
||||
# load images
|
||||
def load_image(path):
|
||||
print("[INFO] Loading image...")
|
||||
# note although trivial, a method was created so the way in which a file is loaded can be easily changed
|
||||
def load_image(path: str):
|
||||
# print("[INFO] Loading image...")
|
||||
image = cv2.imread(path)
|
||||
return image
|
||||
|
||||
|
@ -122,7 +153,7 @@ def load_files(paths):
|
|||
return (images, videos)
|
||||
|
||||
# filter images based on filesize
|
||||
def filter_filesize(paths):
|
||||
def filter_filesize(paths, thresh=0.35):
|
||||
print("[INFO] Filtering by filesize...")
|
||||
filesizes = []
|
||||
filtered_paths = []
|
||||
|
@ -131,7 +162,7 @@ def filter_filesize(paths):
|
|||
filesize = os.path.getsize(path)
|
||||
filesizes.append(filesize)
|
||||
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_max = max(filesizes)
|
||||
filesize_filter = filesize_avg - filesize_std
|
||||
|
@ -157,10 +188,11 @@ def plot_filesizes(paths):
|
|||
fig = plt.figure(figsize =(10, 7))
|
||||
plt.boxplot(data)
|
||||
plt.show()
|
||||
return plt
|
||||
|
||||
# resize image and turn to greyscale
|
||||
def process_image(path, width):
|
||||
print("[INFO] Processing image...")
|
||||
# print("[INFO] Processing image...")
|
||||
image = cv2.imread(path)
|
||||
height = int(image.shape[0] * (width / image.shape[0]))
|
||||
image = cv2.resize(image, (width, height))
|
||||
|
@ -169,38 +201,63 @@ def process_image(path, width):
|
|||
|
||||
# filter images based on contrast
|
||||
def filter_contrast(paths, thresh=0.35):
|
||||
print("[INFO] Filtering by contrast...")
|
||||
# print("[INFO] Filtering by contrast...")
|
||||
filtered_paths = []
|
||||
for path in paths:
|
||||
for path in tqdm(paths, desc="Filtering contrast"):
|
||||
if path.lower().endswith(video_formats):
|
||||
continue
|
||||
print(path)
|
||||
# print(path)
|
||||
image = process_image(path, 500)
|
||||
if is_low_contrast(image, thresh):
|
||||
print("[INFO] Low contrast")
|
||||
# print("[INFO] Low contrast")
|
||||
continue
|
||||
else:
|
||||
print("[INFO] High contrast")
|
||||
# print("[INFO] High contrast")
|
||||
filtered_paths.append(path)
|
||||
return filtered_paths
|
||||
|
||||
# filter images based on brightness
|
||||
def filter_brightness(paths):
|
||||
print("[INFO] Filtering by brightness...")
|
||||
def filter_brightness(paths, thresh=0.35):
|
||||
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
|
||||
def filter_focus(paths):
|
||||
def filter_focus(paths, thresh=0.35):
|
||||
print("[INFO] Filtering by focus/blurriness...")
|
||||
filtered_paths = []
|
||||
# read images in greyscale
|
||||
for path in paths:
|
||||
for path in tqdm(paths, desc="Filtering focus"):
|
||||
if path.lower().endswith(video_formats):
|
||||
continue
|
||||
print(path)
|
||||
# print(path)
|
||||
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})"
|
||||
if blurry:
|
||||
print(("[INFO] {}: " + blurStats).format(path, mean))
|
||||
# print(("[INFO] {}: " + blurStats).format(path, mean))
|
||||
continue
|
||||
else:
|
||||
filtered_paths.append(path)
|
||||
return filtered_paths
|
||||
|
@ -209,31 +266,81 @@ def filter_focus(paths):
|
|||
def rank_images():
|
||||
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.add_argument("-i", "--input", type=os.path.abspath, required=True, nargs="+",
|
||||
help="path to video or image folder")
|
||||
parser.add_argument("-c", "--config", type=os.path.abspath, help="path to config file")
|
||||
args = vars(parser.parse_args())
|
||||
|
||||
paths = filter_paths(args["input"])
|
||||
|
||||
# load in config file
|
||||
if args["config"] is not None:
|
||||
autophotoConf = load_config(args["config"])
|
||||
else:
|
||||
autophotoConf = load_config()
|
||||
|
||||
# Order and selection of operations from config file
|
||||
for imageFilter in autophotoConf["filters"]:
|
||||
n_of_images_before = len(paths)
|
||||
filter_to_function(imageFilter)
|
||||
n_of_images_after = len(paths)
|
||||
# Load values for options
|
||||
if autophotoConf["brightness_options"]["threshold"] is not None:
|
||||
brightness_thresh = autophotoConf["brightness_options"]["threshold"]
|
||||
if autophotoConf["focus_options"]["threshold"] is not None:
|
||||
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
|
||||
diff = n_of_images_before - n_of_images_after
|
||||
print("[INFO] Filtered {}/{} images via {} filtering.".format(
|
||||
n_of_images_after, n_of_images_before, imageFilter))
|
||||
paths = filter_paths(args["input"])
|
||||
print("[INFO] Loaded {} objects.".format(len(paths)))
|
||||
prior_paths = []
|
||||
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"]:
|
||||
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__)
|
||||
projectRoot = abspath(os.path.join(script_directory, "../.."))
|
||||
#projectRoot = "/src/"
|
||||
print(projectRoot)
|
||||
tensorImagesPath = os.path.join(projectRoot, "src/autophotographer/tensorImages.pt")
|
||||
tensorRatingsPath = os.path.join(projectRoot, "src/autophotographer/tensorRatings.pt")
|
||||
tensorArrayPath = os.path.join(projectRoot, "src/autophotographer/tensorArray.pt")
|
||||
# tensorImagesPath = os.path.join(projectRoot, "src/autophotographer/tensorImages.pt")
|
||||
# tensorRatingsPath = os.path.join(projectRoot, "src/autophotographer/tensorRatings.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")
|
||||
dataframePath = os.path.join(projectRoot, "src/autophotographer/dataframe.csv")
|
||||
dataframePath = os.path.join(script_directory, "dataframe.csv")
|
||||
|
||||
if not datasetDir == "":
|
||||
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
|
||||
# Note: Possible filters include: brightness, filesize, contrast, focus
|
||||
filters:
|
||||
- brightness
|
||||
- filesize
|
||||
|
@ -9,21 +10,25 @@ filters:
|
|||
- focus
|
||||
|
||||
# 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:
|
||||
threshold: 0.35
|
||||
threshold: 0.25
|
||||
|
||||
# Options for focus filter
|
||||
# Options for filesize filter
|
||||
filesize_options:
|
||||
threshold: 0.35
|
||||
|
||||
# Options for focus filter
|
||||
# Options for contrast filter
|
||||
contrast_options:
|
||||
threshold: 0.35
|
||||
|
||||
# Options for focus filter
|
||||
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 os
|
||||
from os.path import abspath
|
||||
from autophotographer import config
|
||||
from autophotographer import dataset
|
||||
from cnn import config
|
||||
from cnn import dataset
|
||||
from torchvision import transforms
|
||||
import matplotlib.pyplot as plt
|
||||
from torch import nn
|
||||
|
|
Reference in a new issue