start with poetry

This commit is contained in:
Simon Milvert 2021-02-10 21:19:53 +01:00
parent 61db3d9216
commit 662e10d1a4
11 changed files with 91 additions and 67 deletions

View File

@ -11,7 +11,7 @@ image = cv2.imread('capture.png')
# Create a window # Create a window
cv2.namedWindow('image') cv2.namedWindow('image')
# dp, minDist, circles=None, param1=None, param2=None, minRadius=None, maxRadius=None)
# Create trackbars for color change # Create trackbars for color change
# Hue is from 0-179 for Opencv # Hue is from 0-179 for Opencv
cv2.createTrackbar('dp', 'image', 0, 300, nothing) cv2.createTrackbar('dp', 'image', 0, 300, nothing)
@ -33,7 +33,7 @@ cv2.setTrackbarPos('maxRadius', 'image', 50)
dp = minDist = param1 = param2 = minRadius = maxRadius = 0 dp = minDist = param1 = param2 = minRadius = maxRadius = 0
pdp = pminDist = pparam1 = pparam2 = pminRadius = pmaxRadius = 0 pdp = pminDist = pparam1 = pparam2 = pminRadius = pmaxRadius = 0
while (1): while True:
# Get current positions of all trackbars # Get current positions of all trackbars
dp = cv2.getTrackbarPos('dp', 'image') dp = cv2.getTrackbarPos('dp', 'image')
minDist = cv2.getTrackbarPos('minDist', 'image') minDist = cv2.getTrackbarPos('minDist', 'image')
@ -44,16 +44,17 @@ while (1):
img = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) img = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gradient = cv2.HOUGH_GRADIENT gradient = cv2.HOUGH_GRADIENT
circles = cv2.HoughCircles(img, gradient, dp/100.0, minDist, circles = cv2.HoughCircles(img, gradient, dp/100.0, minDist, param1=param1,
param1=param1, param2=param2, minRadius=minRadius, param2=param2, minRadius=minRadius,
maxRadius=maxRadius) maxRadius=maxRadius)
# Print if there is a change in HSV value # Print if there is a change in HSV value
if ((pdp != dp) | (pminDist != minDist) | (pparam1 != param1) | ( if ((pdp != dp) | (pminDist != minDist) | (pparam1 != param1) | (
pparam2 != param2) | (pminRadius != minRadius) | ( pparam2 != param2) | (pminRadius != minRadius) | (
pmaxRadius != maxRadius)): pmaxRadius != maxRadius)):
print("dp: {}, minDist: {}, param1: {}, param2: {}, minRadius: {}, maxRadius: {}" print(f"dp: {dp}, minDist: {minDist}, param1: {param1}, "
.format(dp, minDist, param1, param2, minRadius, maxRadius)) f"param2: {param2}, minRadius: {minRadius}, "
f"maxRadius: {maxRadius}")
pdp = dp pdp = dp
pminDist = minDist pminDist = minDist
pparam1 = param1 pparam1 = param1

View File

@ -1,9 +1,12 @@
import cv2 import cv2
import numpy as np import numpy as np
def nothing(x): def nothing(x):
print(x)
pass pass
# Load image # Load image
image = cv2.imread('capture.png') image = cv2.imread('capture.png')
@ -28,7 +31,7 @@ cv2.setTrackbarPos('VMax', 'image', 255)
hMin = sMin = vMin = hMax = sMax = vMax = 0 hMin = sMin = vMin = hMax = sMax = vMax = 0
phMin = psMin = pvMin = phMax = psMax = pvMax = 0 phMin = psMin = pvMin = phMax = psMax = pvMax = 0
while(1): while True:
# Get current positions of all trackbars # Get current positions of all trackbars
hMin = cv2.getTrackbarPos('HMin', 'image') hMin = cv2.getTrackbarPos('HMin', 'image')
sMin = cv2.getTrackbarPos('SMin', 'image') sMin = cv2.getTrackbarPos('SMin', 'image')
@ -47,8 +50,15 @@ while(1):
result = cv2.bitwise_and(image, image, mask=mask) result = cv2.bitwise_and(image, image, mask=mask)
# Print if there is a change in HSV value # Print if there is a change in HSV value
if((phMin != hMin) | (psMin != sMin) | (pvMin != vMin) | (phMax != hMax) | (psMax != sMax) | (pvMax != vMax) ): if(
print("(hMin = %d , sMin = %d, vMin = %d), (hMax = %d , sMax = %d, vMax = %d)" % (hMin , sMin , vMin, hMax, sMax , vMax)) (phMin != hMin) |
(psMin != sMin) |
(pvMin != vMin) |
(phMax != hMax) |
(psMax != sMax) |
(pvMax != vMax)):
print(f"(hMin = {hMin} , sMin = {sMin}, vMin = {vMin}), "
f"(hMax = {hMax}, sMax = {sMax}, vMax = {vMax})")
phMin = hMin phMin = hMin
psMin = sMin psMin = sMin
pvMin = vMin pvMin = vMin

View File

@ -1,5 +1,6 @@
import cv2 import cv2
def get_video(): def get_video():
camera = cv2.VideoCapture() camera = cv2.VideoCapture()
camera.open('http://10.0.0.22:81') camera.open('http://10.0.0.22:81')
@ -12,5 +13,6 @@ def get_video():
cv2.waitKey(1) cv2.waitKey(1)
pass pass
if __name__ == '__main__': if __name__ == '__main__':
get_video() get_video()

View File

@ -0,0 +1 @@
__version__ = "0.1.0"

View File

View File

@ -1,6 +1,5 @@
import yaml import yaml
import logging
def get_config(config_filepath: str) -> dict: def get_config(config_filepath: str) -> dict:
with open(config_filepath) as f: with open(config_filepath) as f:
@ -9,14 +8,14 @@ def get_config(config_filepath: str) -> dict:
def create_logger(): def create_logger():
import multiprocessing, logging import multiprocessing
import logging
logger = multiprocessing.get_logger() logger = multiprocessing.get_logger()
logger.setLevel(logging.INFO) logger.setLevel(logging.INFO)
formatter = logging.Formatter(\ formatter = logging.Formatter('[%(asctime)s| %(levelname)s| %(message)s')
'[%(asctime)s| %(levelname)s| %(message)s') import os.path
import os, os.path if not os.path.exists("logs"):
if not os.path.exists("logs/"): os.makedirs("logs")
os.makedirs("logs/")
handler = logging.FileHandler('logs/water.log') handler = logging.FileHandler('logs/water.log')
handler.setFormatter(formatter) handler.setFormatter(formatter)

View File

@ -1,12 +1,12 @@
import os import os
import time import time
from queue import Queue
from threading import Thread from threading import Thread
from src.helpers import get_config, create_logger from src.water_meter.helpers import get_config, create_logger
from src.mqtt import get_mqtt_client from src.water_meter.mqtt import get_mqtt_client
from src.water import ReportAmount, Water from src.water_meter.water import ReportAmount
from src.water_meter import WaterMeter from src.water_meter.water_meter import WaterMeter
from queue import Queue
CONFIG_FILE_PATH = os.getenv("MQTT_CAMERA_CONFIG", "./config.yml") CONFIG_FILE_PATH = os.getenv("MQTT_CAMERA_CONFIG", "./config.yml")
CONFIG = get_config(CONFIG_FILE_PATH) CONFIG = get_config(CONFIG_FILE_PATH)
@ -16,15 +16,17 @@ MQTT_PORT = CONFIG["mqtt"]["port"]
def producer(): def producer():
logger = create_logger() logger_producer = create_logger()
logger.info("From producer") logger_producer.info("From producer")
water_meter = WaterMeter('http://10.0.0.22:81', img='capture_4.png', debug=False) water_meter = WaterMeter('http://10.0.0.22:81',
img='capture_4.png',
debug=False)
water_meter.loop(q) water_meter.loop(q)
def consumer(): def consumer():
logger = create_logger() logger_consumer = create_logger()
logger.info("From consumer") logger_consumer.info("From consumer")
evaluator = ReportAmount(client, topic='water_meter/litre') evaluator = ReportAmount(client, topic='water_meter/litre')
while True: while True:
water = q.get(True) water = q.get(True)
@ -32,28 +34,28 @@ def consumer():
def main(): def main():
client = get_mqtt_client()
client.connect(MQTT_BROKER, port=MQTT_PORT)
time.sleep(5) time.sleep(5)
while True: while True:
from random import randrange from random import randrange
value = randrange(10) value = randrange(10)
client.publish('water_meter/litre', 1) client.publish('water_meter/litre', value)
time.sleep(3) time.sleep(3)
def main2(): def main2():
producer()
consumer_thread = Thread(target=consumer) consumer_thread = Thread(target=consumer)
consumer_thread.daemon = True consumer_thread.daemon = True
consumer_thread.start() consumer_thread.start()
producer()
logger = create_logger()
logger.info("From main")
q = Queue()
client = get_mqtt_client()
client.connect(MQTT_BROKER, port=MQTT_PORT)
if __name__ == '__main__': if __name__ == '__main__':
logger = create_logger()
logger.info("From main")
q = Queue()
client = get_mqtt_client()
client.connect(MQTT_BROKER, port=MQTT_PORT)
main2() main2()

View File

@ -2,9 +2,10 @@
Some boilerplate code to handle MQTT. Some boilerplate code to handle MQTT.
""" """
import os import os
from paho.mqtt import client as mqtt from paho.mqtt import client as mqtt
from src.helpers import get_config from src.water_meter.helpers import get_config
CONFIG_FILE_PATH = os.getenv("MQTT_CAMERA_CONFIG", "./config.yml") CONFIG_FILE_PATH = os.getenv("MQTT_CAMERA_CONFIG", "./config.yml")
CONFIG = get_config(CONFIG_FILE_PATH) CONFIG = get_config(CONFIG_FILE_PATH)

View File

@ -1,9 +1,11 @@
from dataclasses import dataclass
import time import time
from threading import Thread from dataclasses import dataclass
from queue import Queue from queue import Queue
from threading import Thread
from .helpers import create_logger from .helpers import create_logger
@dataclass @dataclass
class Water: class Water:
percent_of_a_litre: int percent_of_a_litre: int
@ -15,6 +17,7 @@ def coroutine(fn):
v = fn(*args, **kwargs) v = fn(*args, **kwargs)
v.send(None) v.send(None)
return v return v
return wrapper return wrapper
@ -45,20 +48,19 @@ class ReportAmount:
self.logger.info(f"New litre, publish, amount: {self.litre}") self.logger.info(f"New litre, publish, amount: {self.litre}")
self.last_send_timestamp = water.timestamp self.last_send_timestamp = water.timestamp
self.current_state = self.reported self.current_state = self.reported
#print(f"REPORT: Percentage is {percentage}, time {water.timestamp}") # print(f"REPORT: Percentage is {percentage}, time {water.timestamp}")
@coroutine @coroutine
def _reported(self): def _reported(self):
while True: while True:
water = yield water = yield
percentage = water.percent_of_a_litre percentage = water.percent_of_a_litre
time_diff = water.timestamp - self.last_send_timestamp # time_diff = water.timestamp - self.last_send_timestamp
if percentage > 25: if percentage > 25:
self.current_state = self.redo self.current_state = self.redo
# print(f"REPORTED: Wait until percentage is 50, {percentage}" # print(f"REPORTED: Wait until percentage is 50, {percentage}"
# f", timediff: {time_diff}") # f", timediff: {time_diff}")
@coroutine @coroutine
def _redo(self): def _redo(self):
while True: while True:
@ -67,7 +69,6 @@ class ReportAmount:
if percentage < 20: if percentage < 20:
print("Change to report") print("Change to report")
self.current_state = self.report self.current_state = self.report
#print(f"REDO: Percentage is {percentage}, time {water.timestamp}")
def producer(): def producer():
@ -77,7 +78,7 @@ def producer():
def consumer(): def consumer():
evaluator = ReportAmount() evaluator = ReportAmount(None, topic='water_meter/litre')
while True: while True:
water = q.get(True) water = q.get(True)
evaluator.send(water) evaluator.send(water)
@ -95,6 +96,3 @@ if __name__ == '__main__':
t1.start() t1.start()
q.join() q.join()

View File

@ -1,14 +1,13 @@
import math import math
import sys
import time import time
import cv2 import cv2
import os
import numpy as np
import imutils import imutils
import numpy as np
from scipy.spatial import distance as dist from scipy.spatial import distance as dist
from .water import Water
from .helpers import create_logger from .helpers import create_logger
from .water import Water
class WaterMeter(object): class WaterMeter(object):
@ -43,6 +42,7 @@ class WaterMeter(object):
img = cv2.imread(self.img) img = cv2.imread(self.img)
self.get_degree(img) self.get_degree(img)
# noinspection PyUnusedLocal
def loop(self, queue): def loop(self, queue):
bad_frame = 0 bad_frame = 0
while not self._quit: while not self._quit:
@ -62,7 +62,7 @@ class WaterMeter(object):
ret, current_frame = self.cap.read() ret, current_frame = self.cap.read()
# the connection broke, or the stream came to an end # the connection broke, or the stream came to an end
if (not ret) or (current_frame is None): if (not ret) or (current_frame is None):
# ToDo Logging error frame self.logger.error("Bad frame")
bad_frame += 1 bad_frame += 1
continue continue
else: else:
@ -87,6 +87,7 @@ class WaterMeter(object):
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
cv2.putText(current_frame, f"%: {self.percent}", (10, 60), cv2.putText(current_frame, f"%: {self.percent}", (10, 60),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
cv2.imshow("Degree", current_frame) cv2.imshow("Degree", current_frame)
cv2.waitKey(1) cv2.waitKey(1)
@ -99,8 +100,7 @@ class WaterMeter(object):
def get_degree(self, frame): def get_degree(self, frame):
img = frame img = frame
dials = self.find_circle(img) dials = self.find_circle(img)
# Init value out of range
deg = -1
dial_one_litre = [] dial_one_litre = []
if not dials: if not dials:
return -1, img return -1, img
@ -174,8 +174,15 @@ class WaterMeter(object):
except cv2.error: except cv2.error:
return None return None
# Find suitable hsv number by running detect_hsv.py # Find suitable hsv number by running detect_hsv.py
lower_red_hue = self.create_hue_mask(hsv, [0, 100, 100], [10, 255, 255]) lower_red_hue = self.create_hue_mask(hsv,
higher_red_hue = self.create_hue_mask(hsv, [170, 80, 110], [179, 255, 255]) [0, 100, 100],
[10, 255, 255]
)
higher_red_hue = self.create_hue_mask(hsv,
[170, 80, 110],
[179, 255, 255]
)
mask = cv2.bitwise_or(lower_red_hue, higher_red_hue) mask = cv2.bitwise_or(lower_red_hue, higher_red_hue)
needle = cv2.GaussianBlur(mask, (5, 5), 0) needle = cv2.GaussianBlur(mask, (5, 5), 0)
@ -187,7 +194,7 @@ class WaterMeter(object):
def get_contours(self, img, org): def get_contours(self, img, org):
ret, thresh = cv2.threshold(img, 127, 255, 0) ret, thresh = cv2.threshold(img, 127, 255, 0)
contours = cv2.findContours(thresh, cv2.RETR_TREE, contours = cv2.findContours(thresh, cv2.RETR_TREE,
cv2.CHAIN_APPROX_SIMPLE) cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(contours) cnts = imutils.grab_contours(contours)
try: try:
c = max(cnts, key=cv2.contourArea) c = max(cnts, key=cv2.contourArea)
@ -232,11 +239,11 @@ class WaterMeter(object):
height, width, _ = cut.shape height, width, _ = cut.shape
for (x, y) in extreme_points: for (x, y) in extreme_points:
D = dist.euclidean((x, y), (int(height/2), int(width/2))) distance = dist.euclidean((x, y), (int(height/2), int(width/2)))
if not length_from_centre: if not length_from_centre:
length_from_centre = {'x': x, 'y': y, 'distance': D} length_from_centre = {'x': x, 'y': y, 'distance': distance}
elif D > length_from_centre['distance']: elif distance > length_from_centre['distance']:
length_from_centre = {'x': x, 'y': y, 'distance': D} length_from_centre = {'x': x, 'y': y, 'distance': distance}
if self.debug: if self.debug:
cv2.line(cut, (length_from_centre['x'], length_from_centre['y']), cv2.line(cut, (length_from_centre['x'], length_from_centre['y']),
@ -259,8 +266,11 @@ class WaterMeter(object):
self.percent = sum(self.percent_list) / len(self.percent_list) self.percent = sum(self.percent_list) / len(self.percent_list)
self.percent = round(self.percent * 100) self.percent = round(self.percent * 100)
if __name__ == '__main__':
water_meter = WaterMeter('http://10.0.0.22:81', img='capture_4.png', debug=False) if __name__ == '__main__':
water_meter.loop() water_meter = WaterMeter('http://10.0.0.22:81',
#water_meqter.read() img='capture_4.png',
debug=False)
water_meter.loop()
# water_meqter.read()