I have some information (a list of participants to an event) which I want to print out easily. No need for fancy layout, just a table with several columns, and if possible a drawn line in between the lines of text for better readability. Will need to print landscape to make it all fit (can be done via a GtkPageSetup).
I'm using Python, and I'm on Linux so will have to use the GtkPrintUnixDialog interface. I've been searching on Internet but can't find any example on how this could possibly be achieved.
To simplify the problem: it's for my own use only, so known paper size (A4).
The problem that I have is basically two-fold: 1) create a properly formatted text, suitable for printing, and 2) send this to the printer.
Any suggestions on where to start? Or better, complete examples?
I search for my old print examples, but for a start:
You could write to pdf surface, and print pdf, or
put the drawing code on on_print function. Note, it does not print what you see, but what you draw on print surface. Draw the context like a regular cairo context, but a few methods are not available(don't fit in print context) while others, like new page, are added. If I find the example, I will come with a answer more self-explanatory.
Edit: find an ex:
def on_button_clicked(self, widget):
ps = Gtk.PaperSize.new_custom("cc", "cc", 210, 297, Gtk.Unit.MM)
st = Gtk.PrintSettings()
s = Gtk.PageSetup()
s.set_paper_size(ps)
s.set_bottom_margin(4.3, Gtk.Unit.MM)
s.set_left_margin(4.3, Gtk.Unit.MM)
s.set_right_margin(4.3, Gtk.Unit.MM)
s.set_top_margin(4.3, Gtk.Unit.MM)
s.set_orientation(Gtk.PageOrientation.LANDSCAPE)
# ret = Gtk.print_run_page_setup_dialog(self, s, st)
pd = Gtk.PrintOperation()
pd.set_n_pages(1)
pd.set_default_page_setup(s)
pd.connect("begin_print", self.bg)
pd.connect("draw_page", self.draw_page)
# print(ret, s, st)
pd.set_export_filename("test.pdf")
result = pd.run(Gtk.PrintOperationAction.EXPORT, None) #play with action, but for test export first; if it's ok, then action.PRINT
print (result) # handle errors etc.
# Gtk.PaperSize.free(ps) - not needed in py
the above may be on button press or whatever
def draw_page (self, operation, context, page_number):
end = self.layout.get_line_count()
cr = context.get_cairo_context()
cr.set_source_rgb(0, 0, 0)
i = 0
start = 0
start_pos = 0
iter = self.layout.get_iter()
while 1:
if i >= start:
line = iter.get_line()
print(line)
_, logical_rect = iter.get_line_extents()
# x_bearing, y_bearing, lwidth, lheight = logical_rect
baseline = iter.get_baseline()
if i == start:
start_pos = 12000 / 1024.0 # 1024.0 is float(pango.SCALE)
cr.move_to(0 / 1024.0, baseline / 1024.0 - start_pos)
PangoCairo.show_layout_line(cr, line)
i += 1
if not (i < end and iter.next_line()):
break
That's just a basic example. Note that layout is a pango layout:
self.layout = cx.create_pango_layout()
self.layout.set_width(int(w / 4 * Pango.SCALE))
self.layout.set_text(text, len(text))
num_lines = self.layout.get_line_count()
page_height = 0
self.layout.set_font_description(Pango.FontDescription("Georgia Bold 12"))
k = 0
for line in range(num_lines):
if k == 4:
self.layout.set_font_description(Pango.FontDescription("Georgia 10"))
layout_line = self.layout.get_line(line)
ink_rect, logical_rect = layout_line.get_extents()
lheight = 1200
line_height = lheight / 1024.0 # 1024.0 is float(pango.SCALE)
page_height += line_height
k += 1
print ("page_height ", page_height)
copy/paste functional example:
#!/usr/bin/python
from gi.repository import Gtk, Pango, PangoCairo
import cairo
text = '''
Text.
I have some information (a list of participants to an event) which I
want to print out easily.
No need for fancy layout,
just a table with several columns,
and if possible a drawn line in between the lines of
text for better readability.
'''
class MyWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Hello World Printing")
self.button = Gtk.Button(label="Print A Rectangle")
self.button.connect("clicked", self.on_button_clicked)
self.add(self.button)
def on_button_clicked(self, widget):
ps = Gtk.PaperSize.new_custom("cc", "cc", 210, 297, Gtk.Unit.MM)
st = Gtk.PrintSettings()
s = Gtk.PageSetup()
s.set_paper_size(ps)
s.set_bottom_margin(4.3, Gtk.Unit.MM)
s.set_left_margin(4.3, Gtk.Unit.MM)
s.set_right_margin(4.3, Gtk.Unit.MM)
s.set_top_margin(4.3, Gtk.Unit.MM)
s.set_orientation(Gtk.PageOrientation.LANDSCAPE)
# ret = Gtk.print_run_page_setup_dialog(self, s, st)
pd = Gtk.PrintOperation()
pd.set_n_pages(1)
pd.set_default_page_setup(s)
pd.connect("begin_print", self.bg)
pd.connect("draw_page", self.draw_page)
# print(ret, s, st)
pd.set_export_filename("test.pdf")
result = pd.run(Gtk.PrintOperationAction.EXPORT, None)
print (result) # handle errors etc.
# Gtk.PaperSize.free(ps)
def bg(self, op, cx):
w = cx.get_width()
h = cx.get_height()
self.layout = cx.create_pango_layout()
self.layout.set_width(int(w / 4 * Pango.SCALE))
self.layout.set_text(text, len(text))
num_lines = self.layout.get_line_count()
page_height = 0
self.layout.set_font_description(Pango.FontDescription("Georgia Bold 12"))
k = 0
for line in range(num_lines):
if k == 4:
self.layout.set_font_description(Pango.FontDescription("Georgia 10"))
layout_line = self.layout.get_line(line)
ink_rect, logical_rect = layout_line.get_extents()
# print(logical_rect, ink_rect)
# x_bearing, y_bearing, lwidth, lheight = logical_rect
lheight = 1200
line_height = lheight / 1024.0 # 1024.0 is float(pango.SCALE)
page_height += line_height
# page_height is the current location on a page.
# It adds the the line height on each pass through the loop
# Once it is greater then the height supplied by context.get_height
# it marks the line and sets the current page height back to 0
k += 1
print ("page_height ", page_height)
def box(self, w, h, x, y, cx):
w, h = int(w), int(h)
cx.set_font_size(100)
cx.set_source_rgb(0, 0, 0)
cx.rectangle(x, y, w, h)
cx.stroke()
yy = 120
cx.select_font_face("Times", 0, 1)
ex = cx.text_extents("TEGOLA ROMÂNIA SRL")[2]
cx.move_to(w / 2 - ex / 2 + x, 105 + y)
cx.show_text("TEGOLA ROMÂNIA SRL")
ex = cx.text_extents("Str. Plevnei, nr. 5, Buzău")[2]
cx.move_to(w / 2 - ex / 2 + x, 210 + y)
cx.show_text("Str. Plevnei, nr. 5, Buzău")
ex = cx.text_extents("Tel.: 0238/710.280")[2]
cx.move_to(w / 2 - ex / 2 + x, 320 + y)
cx.show_text("Tel.: 0238/710.280")
ex = cx.text_extents("Fax : 0238/710021")[2]
cx.move_to(w / 2 - ex / 2 + x, 415 + y)
cx.show_text("Fax : 0238/710021")
cx.set_font_size(90)
cx.move_to(x + 120, 520 + y)
ex = cx.text_extents("Compoziție:")[2]
cx.show_text("Compoziție:")
cx.select_font_face("Times", 0, 0)
cx.move_to(x + 125 + ex, 520 + y)
cx.show_text("Polimer bituminos, liant și")
cx.move_to(x + 5, 620 + y)
cx.show_text("material de umplutură de înaltă calitate.")
cx.move_to(x + 5, 720 + y)
cx.show_text("Nu conține gudron.")
cx.move_to(x + 5, 800 + y)
cx.select_font_face("Times", 0, 1)
ex = cx.text_extents("Instrucțiuni de utilizare:")[2]
cx.show_text("Instrucțiuni de utilizare:")
cx.select_font_face("Times", 0, 0)
cx.move_to(x + 10 + ex, 800 + y)
cx.show_text("Suprafețele se")
def draw_page1(self, operation, context, page_nr=None):
ctx = context.get_cairo_context()
w = context.get_width()
h = context.get_height()
ww, hh = int(w / 4), int(h / 2)
self.k = 0
for x in range(2):
for y in range(4):
self.box(ww, hh, y * ww, x * hh, ctx)
self.k += 1
print(ctx.get_font_matrix())
def draw_page (self, operation, context, page_number):
end = self.layout.get_line_count()
cr = context.get_cairo_context()
cr.set_source_rgb(0, 0, 0)
i = 0
start = 0
start_pos = 0
iter = self.layout.get_iter()
while 1:
if i >= start:
line = iter.get_line()
print(line)
_, logical_rect = iter.get_line_extents()
# x_bearing, y_bearing, lwidth, lheight = logical_rect
baseline = iter.get_baseline()
if i == start:
start_pos = 12000 / 1024.0 # 1024.0 is float(pango.SCALE)
cr.move_to(0 / 1024.0, baseline / 1024.0 - start_pos)
PangoCairo.show_layout_line(cr, line)
i += 1
if not (i < end and iter.next_line()):
break
win = MyWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
Don't forget to change action to Gtk.PrintOperationAction.PRINT for real printing.
Related
2 months ago i ordered 3 RBG Matrix panel + an ada fruit matrix bonnet for Raspberrypi to setup a matrix display showing my google Calendar. suddenly the display shows a big redstripe in the upper half of the display. i also cant control the brightness. if the brightness is to low nothing but the red stripe is visisible.i ordered a second copy of the bonnet hoping i incedently destroyed something while sodering or due to too high currents of my powersuply (actually 5V max 0.7A, used to be higher, 12v). at software level i tried i few different args with no difference.
here dome images
at the beginning of the project everything was fine, no stripe nothing, then suddenly
i use 1 matrix P4 matrix from adafruit and one without brand from ebay
thank you for helping me
regards Anika
currently use RGBMAtrix lib with
sudo python3 time.py --led-cols=64 --led-gpio-mapping=adafruit-hat-pwm --led-slowdown-gpio=5 --led-no-drop-privs --led-pwm-bits=1 --led-chain=2 --led-panel-type=FM6126A --led-pixel-mapper=Rotate:180
this i the python code for drive 2 matrixes in chain
#!/usr/bin/env python
# Display a runtext with double-buffering.
from samplebase import SampleBase
from rgbmatrix import graphics, RGBMatrix, RGBMatrixOptions
from datetime import datetime, timedelta
import requests, json, time, _thread
##################################################################################################
##################################################################################################
##################################################################################################
class Color():
GREEN = graphics.Color(0 , 255, 0)
BLACK = graphics.Color(0 , 0 , 0)
##################################################################################################
##################################################################################################
##################################################################################################
class Pref(SampleBase):
#TEXT_TIME_REVERSED = False
#FIRST_EVENT_DETAILS = False
INLINE_TIME = True
INLINE_TIME_COL = 6.5
BEGIN_SECOND_DETAIL = 60
MINUTE_COUNT_MAX = 60
MINUTE_BLINK_MAX = 15
NIGHT_OFF = 22
DAY_ON = 4
##################################################################################################
##################################################################################################
##################################################################################################
class MatrixCal(SampleBase):
def __init__(self, *args, **kwargs):
super(MatrixCal, self).__init__(*args, **kwargs)
#self.parser.add_argument("-t", "--text", help="The text to scroll on the RGB LED panel", default="Hello world!")
def run(self):
#make canvas and grafics
offscreen_canvas = self.matrix.CreateFrameCanvas()
secondary_canvas = self.matrix.CreateFrameCanvas()
#font
font_height = 8
font_width = 5
font = graphics.Font()
font.LoadFont("../../../fonts/5x8_custom.bdf")
global data, dt0
data = {"events":[], "annc":[], "todos":[]}
data_ttl = 1 #minute
data_error_retry = 10#mintes
#some vars
format_date_time_second = '%Y-%m-%dT%H:%M:%S'
format_time = "%H:%M"
pos = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
skip_next_event = False
screen_width = offscreen_canvas.width
screen_height = offscreen_canvas.height
screen_main = screen_width
if Pref.INLINE_TIME: screen_main = screen_width - font_width*Pref.INLINE_TIME_COL
tlen = 0
f_dub_ev = False
f_gehen_ev = False
f_no_blink = False
# DEF ###################################################################################
def drawText(_x, _y, _text, _color=Color.GREEN, _font=font):
return graphics.DrawText(offscreen_canvas, _font, _x, _y,_color, _text)
def drawLine(_x, _y, _w, _h, _color):
graphics.DrawLine(offscreen_canvas, _x, _y, _w, _h, _color)
def clearArea(x, y, w, h, _color=Color.BLACK):
for j in range(0, h):
graphics.DrawLine(offscreen_canvas, x, y+j, x+w-1, y+j, _color)
def showMinuteCount(time_diff, ev):
#show minutes count
if dt_start>dt0 and (time_diff<=Pref.MINUTE_COUNT_MAX or ('description' in ev and "display_type_duration" in ev['description'])):
if sec%2==0 and time_diff<=Pref.MINUTE_BLINK_MAX and not f_no_blink :
return ""
else:
if time_diff==0:return "jetzt"
else: return "ʼn{: >2d}mʼn".format(time_diff)
elif dt_start<dt0 or ('description' in ev and "display_type_duration" in ev['description']):
time_diff = int((dt_end-dt0).seconds/60)
if time_diff<=Pref.MINUTE_COUNT_MAX:
return str(time_diff) + "mʼn"
else:
if "schlafen" in ev['summary']:
return "noch " + str(dt_end-dt0)[0:4] +"h"
return "-"+dt_end.strftime("%H:%M")
else:
return dt_start.strftime("%H:%M")
def getData(a):
#api access
deploment_id = "THATS_CONFIDENTIAL"
access_token = "THAT_TOO"
url = "https://script.google.com/macros/s/"+deploment_id+"/exec?token="+access_token
next_data_load = datetime.now();
global data
while True:
#load data from api
dt0 = datetime.now()
if(dt0 > next_data_load):
print(dt0.strftime("%H:%M:%S") + " aquiring new data. next in " + str(data_ttl)+" Minute")
try:
r = requests.get(url)
r.raise_for_status()
data = json.loads(r.text)['data']
except requests.exceptions.HTTPError as errh:
print ("Http Error:",errh)
data['annc'].append({"type":"warning", "text":"HTTP " + str(errh.response.status_code) + " - Es gab ein Problem beim empfangen der Daten"})
except requests.exceptions.ConnectionError as errc:
print ("Error Connecting:",errc)
data['annc'].append({"type":"warning", "text":"Es gab ein Problem bei der Verbindung"})
except requests.exceptions.Timeout as errt:
print ("Timeout Error:",errt)
data['annc'].append({"type":"warning", "text":"Zeitüberschreitung beim laden der Daten"})
except requests.exceptions.RequestException as err:
print ("OOps: Something Else",err)
data['annc'].append({"type":"warning", "text":"Es gab ein Problem beim laden der Daten"})
except Exception as err:
print ("OOps: Something unexpected happend",err)
finally:
next_data_load = datetime.now() + timedelta(minutes=data_ttl);
#end if
time.sleep(1)
#end while
#end def getData
#def getWeather():
#Nachmittags wird es bewölkt. 🌡 min 13°C, max 23°C, ⌀ 20°C
#########################################################################################
#start data thread
_thread.start_new_thread(getData,(99,))
#data thread
while True:
offscreen_canvas.Clear()
if len(data['todos'])>0:screen_main=64
else: screen_main = screen_width
#determine whether main screen is large enought to display events with inline time
Pref.INLINE_TIME=screen_main>64;
#current date and time
dt0 = datetime.now()
sec = int(datetime.now().strftime("%S"))
hour = int(datetime.now().strftime("%H"))
ms = int(datetime.now().strftime("%f")[:-3])
#nacht abschaltung von helligkeit
#if False and Pref.NIGHT_OFF <= hour or hour < Pref.DAY_ON: self.matrix.brightness = 10
#else:
#self.matrix.brightness = 80
#reset screen vars
screen_y = font_height-1
detail_line = not Pref.INLINE_TIME
#print max 4 independet lines
index = 0
line = 0
#when no data available dim screen and only print time
if len(data['events'])==0:
#self.matrix.brightness = 10
graphics.DrawText(offscreen_canvas, font, screen_width-( 5 *font_width), font_height-1 ,Color.GREEN, datetime.now().strftime("%H:%M"))
else:
for todo in data['todos']:
t_title = todo['title']
if index==0:
clearArea(screen_main, 0, screen_width-screen_main, 8, Color.GREEN)
graphics.DrawText(offscreen_canvas, font, screen_width-( 12 *font_width), font_height-1 ,Color.BLACK, datetime.now().strftime("%d.%m. %H:%M"))
screen_y += font_height
#runtext optimization
if len(t_title)*font_width>screen_main-16: t_title = t_title+" "+t_title
else: pos[index+4] = screen_main + font_width+2
#display todo title
tlen = drawText(pos[index+4], screen_y, t_title)
clearArea(0, 8, screen_main+8, 32)
#move line if its longer then screen
if tlen > screen_main-16:
pos[index+4] -= 1
if (tlen/2-(font_width))*-1+screen_main+8> pos[index+4]:
pos[index+4] = screen_main + font_width+12
#graphics.DrawText(secondary_canvas, font, pos[index+4], screen_y ,Color.GREEN, todo['title'])
#graphics.DrawText(offscreen_canvas, font, screen_main+2, 15 ,Color.GREEN, "-")
graphics.DrawText(offscreen_canvas, font, screen_main+2, 15 ,Color.GREEN, "-")
if len(data['todos'])>1:graphics.DrawText(offscreen_canvas, font, screen_main+2, 23 ,Color.GREEN, "-")
if len(data['todos'])>2:graphics.DrawText(offscreen_canvas, font, screen_main+2, 31 ,Color.GREEN, "-")
drawLine(screen_main, 0, screen_main, screen_height, Color.GREEN)
screen_y += font_height
t_title = ""
index +=1
if screen_y>32:break
#end for todo
if len(data['todos'])>0:
clearArea(0, screen_main, screen_width-screen_main, screen_height)
#reset screen_y
screen_y = font_height-1
index =0
for ev in data['events']:
#events params
dt_start = datetime.strptime(ev['begin'][0:18], format_date_time_second)
dt_end = datetime.strptime(ev['end'][0:18], format_date_time_second)
time_diff = int((dt_start-dt0).seconds/60)
ev_summary = ev['summary']
#skip ended events or when event is from main cal and dark blue
if dt_end<=dt0 or time_diff==0 or ev_summary.startswith('#') or ('color' in ev and ev['color'] == 9): continue
#parallel events
b0 = data['events'][index]['begin']==data['events'][index+1]['begin']
b1 = (datetime.strptime(data['events'][index]['begin'][0:18], format_date_time_second)<dt0 and datetime.strptime(data['events'][index+1]['begin'][0:18], format_date_time_second)<dt0)
if (b0 or b1) and data['events'][index]['end']==data['events'][index+1]['end']:
f_dub_ev = True
index +=1 #skip ev
continue
#event details
if f_dub_ev: ev_summary = data['events'][index-1]['summary'] + " & " + ev_summary;
#skip gehen event and attach it to next event
if ev_summary.replace(">", "")=="gehen":
f_gehen_ev = True
data['events'][index+1]['travel_start'] = ev['begin']
continue
if ev_summary.startswith("-"):f_no_blink = True
#replace control chars
if ev_summary.startswith(">"):
#minute_blink_max = 15
ev_summary = ev_summary[1:len(ev_summary)]
ev_summary = ev_summary.replace(">>", "")
ev_summary = ev_summary.replace("schlafen>", "schlafen")
if f_no_blink:ev_summary = ev_summary[1:len(ev_summary)]
#runtext optimization
if len(ev_summary)*font_width>screen_main and (line>1 and f_dub_ev): ev_summary = ev_summary+" "+ev_summary
else: pos[line] = 0
#display main
tlen = drawText(pos[line], screen_y, ev_summary)
#move line if its longer then screen
if tlen > screen_main and (detail_line or Pref.INLINE_TIME):
pos[line] -= 1
if (tlen/2-(font_width))*-1>pos[line]:
pos[line] = font_width+4
#calculate time difference
# show second detail line when time time has come
if time_diff<=Pref.BEGIN_SECOND_DETAIL or dt_start<dt0 and dt_end>dt0: detail_line=not Pref.INLINE_TIME
if Pref.INLINE_TIME:
x = screen_width-( Pref.INLINE_TIME_COL *font_width)
clearArea(x, screen_y-7, Pref.INLINE_TIME_COL*font_width, font_height)
text = showMinuteCount(time_diff, ev)
x = screen_width-( len(text) *font_width)
drawText (x, screen_y, text)
if detail_line or Pref.INLINE_TIME:
if detail_line:
detail_line = False
screen_y += font_height
text = showMinuteCount(time_diff, ev)
if 'travel_start' in ev:
if Pref.INLINE_TIME: screen_y += font_height
blink_go = 15
if data['events'][index-1]['summary']=='>>>gehen': blink_go = 60
dt_travel = datetime.strptime(ev['travel_start'][0:18], format_date_time_second)
travel_diff = int((dt_travel-dt0).seconds/60)
hz=sec%20<=9
if travel_diff<=15: hz=sec%2==0;
#elif travel_diff<15: hz=sec%4<=1;
if Pref.INLINE_TIME:text = ""
else: text = " >"+text
if travel_diff <= Pref.MINUTE_COUNT_MAX:
if hz and travel_diff<=blink_go :
#text = text
if not Pref.INLINE_TIME:text = "gehen" + text
#wechsel blinken gehen mit zeit/"jetzt"
elif not Pref.INLINE_TIME:
if travel_diff==0: text="jetzt" + text
else: text= str(travel_diff) + "mʼn" + text
#wechsel blinken gehen in zeit/jetzt gehen mit leerzeile
elif Pref.INLINE_TIME:
if travel_diff<=0 : text="jetzt gehen"
else: text= "gehen ʼn{: >2d}mʼn".format(travel_diff)
elif not Pref.INLINE_TIME:
text = dt_travel.strftime("%H:%M") + text
else:
text = "gehen "+dt_travel.strftime("%H:%M")
#draw the text to the line
tl = int(len(text))
drawText( screen_main-( tl *font_width), screen_y, text)
#end if detail_line or Pref.INLINE_TIME:
f_dub_ev = False
f_gehen_ev = False
f_no_blink = False
#incrementation & loop break conditions
index +=1
line +=1
screen_y += font_height
if screen_y>screen_height:break
#end for
#end else of events len == 0
#annc = [{"type":"warning", "text":"Es dd"}]
#runtext announcement
if len(data['annc'])>0 and False:
#clear last line
clearArea(0, screen_height-font_height, screen_width, 8)
#get text, double it for smooth runtext animation
annc_text = data['annc'][0]['text']
annc_text = annc_text+" "+annc_text
alen = len(annc_text)*font_width
pos[-1] -= 1
if (alen/2-(2*font_width))*-1>pos[-1]:
pos[-1] = 2*font_width+4
graphics.DrawText(offscreen_canvas, font, pos[-1], screen_height-1 ,Color.GREEN, annc_text)
clearArea(0, screen_height-font_height, 8, 8)
#graphics.DrawText(offscreen_canvas, font, 0, screen_height-1 ,Color.GREEN, "ⓘ")
graphics.DrawText(offscreen_canvas, font, 0, screen_height-1 ,Color.GREEN, "⚠")
#offscreen_canvas = self.matrix.SwapOnVSync(secondary_canvas)
offscreen_canvas = self.matrix.SwapOnVSync(offscreen_canvas)
time.sleep(0.07)
#end while
#end def run(self)
# Main function
if __name__ == "__main__":
mcal = MatrixCal()
if (not mcal.process()):
mcal.print_help()
I'm setting up a PPE Detection module using OpenVINO in my Ubuntu 18.04. Although the video input worked well with my webcam dev/video/0 but I wish it can be change to RTSP input. Whenever I put my RTSP Url inside the config.json it doesnt work and show me Either wrong input path or empty line is found. Please check the conf.json file.
Here is the main.py
#!/usr/bin/env python3
from __future__ import print_function
import sys
import os
import cv2
import numpy as np
from argparse import ArgumentParser
import datetime
import json
from inference import Network
# Global vars
cpu_extension = ''
conf_modelLayers = ''
conf_modelWeights = ''
conf_safety_modelLayers = ''
conf_safety_modelWeights = ''
targetDevice = "CPU"
conf_batchSize = 1
conf_modelPersonLabel = 1
conf_inferConfidenceThreshold = 0.7
conf_inFrameViolationsThreshold = 19
conf_inFramePeopleThreshold = 5
use_safety_model = False
padding = 30
viol_wk = 0
acceptedDevices = ['CPU', 'GPU', 'MYRIAD', 'HETERO:FPGA,CPU', 'HDDL']
videos = []
name_of_videos = []
CONFIG_FILE = '../resources/config.json'
is_async_mode = True
class Video:
def __init__(self, idx, path):
if path.isnumeric():
self.video = cv2.VideoCapture(int(path))
self.name = "Cam " + str(idx)
else:
if os.path.exists(path):
self.video = cv2.VideoCapture("rtsp://edwin:Passw0rd#192.168.0.144:554/cam/realmonitor?channel=1&subtype=1")
self.name = "Video " + str(idx)
else:
print("Either wrong input path or empty line is found. Please check the conf.json file")
exit(21)
if not self.video.isOpened():
print("Couldn't open video: " + path)
sys.exit(20)
self.height = int(self.video.get(cv2.CAP_PROP_FRAME_HEIGHT))
self.width = int(self.video.get(cv2.CAP_PROP_FRAME_WIDTH))
self.currentViolationCount = 0
self.currentViolationCountConfidence = 0
self.prevViolationCount = 0
self.totalViolations = 0
self.totalPeopleCount = 0
self.currentPeopleCount = 0
self.currentPeopleCountConfidence = 0
self.prevPeopleCount = 0
self.currentTotalPeopleCount = 0
cv2.namedWindow(self.name, cv2.WINDOW_NORMAL)
self.frame_start_time = datetime.datetime.now()
def get_args():
"""
Parses the argument.
:return: None
"""
global is_async_mode
parser = ArgumentParser()
parser.add_argument("-d", "--device",
help="Specify the target device to infer on; CPU, GPU,"
"FPGA, MYRIAD or HDDL is acceptable. Application will"
"look for a suitable plugin for device specified"
" (CPU by default)",
type=str, required=False)
parser.add_argument("-m", "--model",
help="Path to an .xml file with a trained model's"
" weights.",
required=True, type=str)
parser.add_argument("-sm", "--safety_model",
help="Path to an .xml file with a trained model's"
" weights.",
required=False, type=str, default=None)
parser.add_argument("-e", "--cpu_extension",
help="MKLDNN (CPU)-targeted custom layers. Absolute "
"path to a shared library with the kernels impl",
type=str, default=None)
parser.add_argument("-f", "--flag", help="sync or async", default="async", type=str)
args = parser.parse_args()
global conf_modelLayers, conf_modelWeights, conf_safety_modelLayers, conf_safety_modelWeights, \
targetDevice, cpu_extension, videos, use_safety_model
if args.model:
conf_modelLayers = args.model
conf_modelWeights = os.path.splitext(conf_modelLayers)[0] + ".bin"
if args.safety_model:
conf_safety_modelLayers = args.safety_model
conf_safety_modelWeights = os.path.splitext(conf_safety_modelLayers)[0] + ".bin"
use_safety_model = True
if args.device:
targetDevice = args.device
if "MULTI:" not in targetDevice:
if targetDevice not in acceptedDevices:
print("Selected device, %s not supported." % (targetDevice))
sys.exit(12)
if args.cpu_extension:
cpu_extension = args.cpu_extension
if args.flag == "async":
is_async_mode = True
print('Application running in Async mode')
else:
is_async_mode = False
print('Application running in Sync mode')
assert os.path.isfile(CONFIG_FILE), "{} file doesn't exist".format(CONFIG_FILE)
config = json.loads(open(CONFIG_FILE).read())
for idx, item in enumerate(config['inputs']):
vid = Video(idx, item['video'])
name_of_videos.append([idx, item['video']])
videos.append([idx, vid])
def detect_safety_hat(img):
"""
Detection of the hat of the person.
:param img: Current frame
:return: Boolean value of the detected hat
"""
lowH = 15
lowS = 65
lowV = 75
highH = 30
highS = 255
highV = 255
crop = 0
height = 15
perc = 8
hsv = np.zeros(1)
try:
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
except cv2.error as e:
print("%d %d %d" % (img.shape))
print("%d %d %d" % (img.shape))
print(e)
threshold_img = cv2.inRange(hsv, (lowH, lowS, lowV), (highH, highS, highV))
x = 0
y = int(threshold_img.shape[0] * crop / 100)
w = int(threshold_img.shape[1])
h = int(threshold_img.shape[0] * height / 100)
img_cropped = threshold_img[y: y + h, x: x + w]
if cv2.countNonZero(threshold_img) < img_cropped.size * perc / 100:
return False
return True
def detect_safety_jacket(img):
"""
Detection of the safety jacket of the person.
:param img: Current frame
:return: Boolean value of the detected jacket
"""
lowH = 0
lowS = 150
lowV = 42
highH = 11
highS = 255
highV = 255
crop = 15
height = 40
perc = 23
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
threshold_img = cv2.inRange(hsv, (lowH, lowS, lowV), (highH, highS, highV))
x = 0
y = int(threshold_img.shape[0] * crop / 100)
w = int(threshold_img.shape[1])
h = int(threshold_img.shape[0] * height / 100)
img_cropped = threshold_img[y: y + h, x: x + w]
if cv2.countNonZero(threshold_img) < img_cropped.size * perc / 100:
return False
return True
def detect_workers(workers, frame):
"""
Detection of the person with the safety guards.
:param workers: Total number of the person in the current frame
:param frame: Current frame
:return: Total violation count of the person
"""
violations = 0
global viol_wk
for worker in workers:
xmin, ymin, xmax, ymax = worker
crop = frame[ymin:ymax, xmin:xmax]
if 0 not in crop.shape:
if detect_safety_hat(crop):
if detect_safety_jacket(crop):
cv2.rectangle(frame, (xmin, ymin), (xmax, ymax),
(0, 255, 0), 2)
else:
cv2.rectangle(frame, (xmin, ymin), (xmax, ymax),
(0, 0, 255), 2)
violations += 1
viol_wk += 1
else:
cv2.rectangle(frame, (xmin, ymin), (xmax, ymax), (0, 0, 255), 2)
violations += 1
viol_wk += 1
return violations
def main():
"""
Load the network and parse the output.
:return: None
"""
get_args()
global is_async_mode
nextReq = 1
currReq = 0
nextReq_s = 1
currReq_s = 0
prevVideo = None
vid_finished = [False] * len(videos)
min_FPS = min([videos[i][1].video.get(cv2.CAP_PROP_FPS) for i in range(len(videos))])
# Initialise the class
infer_network = Network()
infer_network_safety = Network()
# Load the network to IE plugin to get shape of input layer
plugin, (batch_size, channels, model_height, model_width) = \
infer_network.load_model(conf_modelLayers, targetDevice, 1, 1, 2, cpu_extension)
if use_safety_model:
batch_size_sm, channels_sm, model_height_sm, model_width_sm = \
infer_network_safety.load_model(conf_safety_modelLayers, targetDevice, 1, 1, 2, cpu_extension, plugin)[1]
while True:
for index, currVideo in videos:
# Read image from video/cam
vfps = int(round(currVideo.video.get(cv2.CAP_PROP_FPS)))
for i in range(0, int(round(vfps / min_FPS))):
ret, current_img = currVideo.video.read()
if not ret:
vid_finished[index] = True
break
if vid_finished[index]:
stream_end_frame = np.zeros((int(currVideo.height), int(currVideo.width), 1),
dtype='uint8')
cv2.putText(stream_end_frame, "Input file {} has ended".format
(name_of_videos[index][1].split('/')[-1]),
(10, int(currVideo.height / 2)),
cv2.FONT_HERSHEY_COMPLEX, 1, (255, 255, 255), 2)
cv2.imshow(currVideo.name, stream_end_frame)
continue
# Transform image to person detection model input
rsImg = cv2.resize(current_img, (model_width, model_height))
rsImg = rsImg.transpose((2, 0, 1))
rsImg = rsImg.reshape((batch_size, channels, model_height, model_width))
infer_start_time = datetime.datetime.now()
# Infer current image
if is_async_mode:
infer_network.exec_net(nextReq, rsImg)
else:
infer_network.exec_net(currReq, rsImg)
prevVideo = currVideo
previous_img = current_img
# Wait for previous request to end
if infer_network.wait(currReq) == 0:
infer_end_time = (datetime.datetime.now() - infer_start_time) * 1000
in_frame_workers = []
people = 0
violations = 0
hard_hat_detection = False
vest_detection = False
result = infer_network.get_output(currReq)
# Filter output
for obj in result[0][0]:
if obj[2] > conf_inferConfidenceThreshold:
xmin = int(obj[3] * prevVideo.width)
ymin = int(obj[4] * prevVideo.height)
xmax = int(obj[5] * prevVideo.width)
ymax = int(obj[6] * prevVideo.height)
xmin = int(xmin - padding) if (xmin - padding) > 0 else 0
ymin = int(ymin - padding) if (ymin - padding) > 0 else 0
xmax = int(xmax + padding) if (xmax + padding) < prevVideo.width else prevVideo.width
ymax = int(ymax + padding) if (ymax + padding) < prevVideo.height else prevVideo.height
cv2.rectangle(previous_img, (xmin, ymin), (xmax, ymax), (0, 255, 0), 2)
people += 1
in_frame_workers.append((xmin, ymin, xmax, ymax))
new_frame = previous_img[ymin:ymax, xmin:xmax]
if use_safety_model:
# Transform image to safety model input
in_frame_sm = cv2.resize(new_frame, (model_width_sm, model_height_sm))
in_frame_sm = in_frame_sm.transpose((2, 0, 1))
in_frame_sm = in_frame_sm.reshape(
(batch_size_sm, channels_sm, model_height_sm, model_width_sm))
infer_start_time_sm = datetime.datetime.now()
if is_async_mode:
infer_network_safety.exec_net(nextReq_s, in_frame_sm)
else:
infer_network_safety.exec_net(currReq_s, in_frame_sm)
# Wait for the result
infer_network_safety.wait(currReq_s)
infer_end_time_sm = (datetime.datetime.now() - infer_start_time_sm) * 1000
result_sm = infer_network_safety.get_output(currReq_s)
# Filter output
hard_hat_detection = False
vest_detection = False
detection_list = []
for obj_sm in result_sm[0][0]:
if (obj_sm[2] > 0.4):
# Detect safety vest
if (int(obj_sm[1])) == 2:
xmin_sm = int(obj_sm[3] * (xmax - xmin))
ymin_sm = int(obj_sm[4] * (ymax - ymin))
xmax_sm = int(obj_sm[5] * (xmax - xmin))
ymax_sm = int(obj_sm[6] * (ymax - ymin))
if vest_detection == False:
detection_list.append(
[xmin_sm + xmin, ymin_sm + ymin, xmax_sm + xmin, ymax_sm + ymin])
vest_detection = True
# Detect hard-hat
if int(obj_sm[1]) == 4:
xmin_sm_v = int(obj_sm[3] * (xmax - xmin))
ymin_sm_v = int(obj_sm[4] * (ymax - ymin))
xmax_sm_v = int(obj_sm[5] * (xmax - xmin))
ymax_sm_v = int(obj_sm[6] * (ymax - ymin))
if hard_hat_detection == False:
detection_list.append([xmin_sm_v + xmin, ymin_sm_v + ymin, xmax_sm_v + xmin,
ymax_sm_v + ymin])
hard_hat_detection = True
if hard_hat_detection is False or vest_detection is False:
violations += 1
for _rect in detection_list:
cv2.rectangle(current_img, (_rect[0], _rect[1]), (_rect[2], _rect[3]), (0, 255, 0), 2)
if is_async_mode:
currReq_s, nextReq_s = nextReq_s, currReq_s
# Use OpenCV if worker-safety-model is not provided
else:
violations = detect_workers(in_frame_workers, previous_img)
# Check if detected violations equals previous frames
if violations == prevVideo.currentViolationCount:
prevVideo.currentViolationCountConfidence += 1
# If frame threshold is reached, change validated count
if prevVideo.currentViolationCountConfidence == conf_inFrameViolationsThreshold:
# If another violation occurred, save image
if prevVideo.currentViolationCount > prevVideo.prevViolationCount:
prevVideo.totalViolations += (
prevVideo.currentViolationCount - prevVideo.prevViolationCount)
prevVideo.prevViolationCount = prevVideo.currentViolationCount
else:
prevVideo.currentViolationCountConfidence = 0
prevVideo.currentViolationCount = violations
# Check if detected people count equals previous frames
if people == prevVideo.currentPeopleCount:
prevVideo.currentPeopleCountConfidence += 1
# If frame threshold is reached, change validated count
if prevVideo.currentPeopleCountConfidence == conf_inFrameViolationsThreshold:
prevVideo.currentTotalPeopleCount += (
prevVideo.currentPeopleCount - prevVideo.prevPeopleCount)
if prevVideo.currentTotalPeopleCount > prevVideo.prevPeopleCount:
prevVideo.totalPeopleCount += prevVideo.currentTotalPeopleCount - prevVideo.prevPeopleCount
prevVideo.prevPeopleCount = prevVideo.currentPeopleCount
else:
prevVideo.currentPeopleCountConfidence = 0
prevVideo.currentPeopleCount = people
frame_end_time = datetime.datetime.now()
cv2.putText(previous_img, 'Total people count: ' + str(
prevVideo.totalPeopleCount), (10, prevVideo.height - 10),
cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2)
cv2.putText(previous_img, 'Current people count: ' + str(
prevVideo.currentTotalPeopleCount),
(10, prevVideo.height - 40),
cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2)
cv2.putText(previous_img, 'Total violation count: ' + str(
prevVideo.totalViolations), (10, prevVideo.height - 70),
cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2)
cv2.putText(previous_img, 'FPS: %0.2fs' % (1 / (
frame_end_time - prevVideo.frame_start_time).total_seconds()),
(10, prevVideo.height - 100),
cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2)
cv2.putText(previous_img, "Inference time: N\A for async mode" if is_async_mode else \
"Inference time: {:.3f} ms".format((infer_end_time).total_seconds()),
(10, prevVideo.height - 130),
cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2)
cv2.imshow(prevVideo.name, previous_img)
prevVideo.frame_start_time = datetime.datetime.now()
# Swap
if is_async_mode:
currReq, nextReq = nextReq, currReq
previous_img = current_img
prevVideo = currVideo
if cv2.waitKey(1) == 27:
print("Attempting to stop input files")
infer_network.clean()
infer_network_safety.clean()
cv2.destroyAllWindows()
return
if False not in vid_finished:
infer_network.clean()
infer_network_safety.clean()
cv2.destroyAllWindows()
break
if __name__ == '__main__':
main()
Here is the config file
{
"inputs": [
{
"video": "rtsp://xxx:xxx#192.168.0.144:554/cam/realmonitor?channel=1&subtype=1"
}
]
}
This is because of the line if os.path.exists(path):. This if condition checks if path points towards an existing file. Your RTSP stream not being a file, it leads to your error.
For example, you can modify this condition to:
if os.path.exists(path) or path.startswith("rtsp"):
By the way, your hard-coded the rtsp stream address within the code, so it will not use your configured path. You may want to replace the hard-coded path with path.
I wrote a rather simple program in Python. Here is the code:
import pygame
import time
from math import *
from random import *
from pygame.locals import *
def mutateBrain(brain):
a = 0
for element in brain:
brain[a][0] = element[0] + (1 * (0.5 - random()))
brain[a][1] = element[1] + (1 * (0.5 - random()))
a = a + 1
return brain;
def generateFirstBrain():
genbrain = []
h = 0;
while randint(0,5) != 0:
asd = [2 * random(), 2 * random()]
genbrain.insert(h, asd)
h = h + 1
return genbrain
pygame.init()
width, height = 640, 480
screen=pygame.display.set_mode((width, height))
screen.fill(pygame.Color(255,255,255))
pygame.draw.rect(screen,(255,0,0),(310,0,30,30))
movesa = generateFirstBrain()
movesb = generateFirstBrain()
movesc = generateFirstBrain()
cola = (255,255,0)
colb = (255,0,255)
colc = (0,255,255)
while 1:
movesa = mutateBrain(movesa)
movesb = mutateBrain(movesb)
movesc = mutateBrain(movesc)
step = 0
acurrentx = 320
acurrenty = 240
bcurrentx = 320
bcurrenty = 240
ccurrentx = 320
ccurrenty = 240
totalsn = 0
if (len(movesa) >= len(movesb)) and (len(movesa) >= len(movesc)):
totalsn = len(movesa)
elif (len(movesb) >= len(movesa)) and (len(movesb) >= len(movesc)):
totalsn = len(movesb)
else:
totalsn = len(movesc)
for g in range(totalsn):
screen.fill(pygame.Color(255,255,255))
pygame.draw.rect(screen,(255,0,0),(305,0,30,30))
try:
acurrentx = acurrentx + 1 - movesa[step][0]
acurrenty = acurrenty + 1 - movesa[step][1]
except IndexError:
acurrentx = acurrentx
try:
bcurrentx = bcurrentx + 1 - movesb[step][0]
bcurrenty = bcurrenty + 1 - movesb[step][1]
except IndexError:
bcurrentx = bcurrentx
try:
ccurrentx = ccurrentx + 1 - movesc[step][0]
ccurrenty = ccurrenty + 1 - movesc[step][1]
except IndexError:
ccurrentx = ccurrentx
pygame.draw.rect(screen,cola,(acurrentx,acurrenty,4,4))
pygame.draw.rect(screen,colb,(bcurrentx,bcurrenty,4,4))
pygame.draw.rect(screen,colc,(ccurrentx,ccurrenty,4,4))
pygame.display.flip()
time.sleep(0.01);
step = step + 1
dista = sqrt((acurrentx - 240) ** 2 + (acurrenty) ** 2)
distb = sqrt((bcurrentx - 240) ** 2 + (bcurrenty) ** 2)
distc = sqrt((ccurrentx - 240) ** 2 + (ccurrenty) ** 2)
if(dista<=distb and dista<=distc):
print("a")
movesl = movesa
elif(distb<=dista and distb<=distc):
print("b")
movesl = movesb
else:
print("c")
movesl = movesc
movesa = mutateBrain(movesl)
movesb = mutateBrain(movesa)
movesc = mutateBrain(movesb)
movesa = mutateBrain(movesa)
time.sleep(0.01)
movesb = mutateBrain(movesb)
time.sleep(0.01)
movesc = mutateBrain(movesc)
while 1:
pygame.display.flip()
for event in pygame.event.get():
if event.type==pygame.QUIT:
pygame.quit()
exit(0)
Here, at the end of the first while loop, movesl always gets the same value no matter how many times I run the mutateBrain function. But it changes so there should be a problem with the random. Could somene please help me with this? Thanks.
Using this worked:
mutateBrain = lambda x: [[y + 0.5 - random() for y in a] for a in x]
I'm creating a function to draw a office tower:
windows are 20 pixels square
the gap between the windows is 10 pixels
the door is 20 pixels wide, 50 pixels tall, and orange
My code doesn't draw it properly:
from graphics import *
from random import *
def add_window(win, nH, nV):
w, h = win.getWidth(), win.getHeight()
rects = []
for x in range(nH):
rects.append([])
for y in range(nV):
r = Rectangle(Point( x *w//nH, y *h//vV),
Point((x+1)*w//nH, (y+1)*h//nV))
window = [ r,
True,
[ 'red', 'green' ]
]
rects[x].append(window)
rects[x][y][0].draw(win)
rects[x][y][0].setOutline('blue')
color = window[2][randint[0,1]]
rects[x][y][0].setFill(color)
return rects
WIN_W, WIN_H = 500, 400
#Top left coner of the building
BLDG_LEFT, BLDG_TOP = 50, 50
#How many floors, how many windows perfloor, window digit and gap
FLOORS, WIN_FLR, WIN_SZ, GAP = 10, 5, 20, 5
win = None
#Syntax : window[x][y]
# [0] : Rectangle() object
# [1] : True/False
windows = []
#--------------------------------------------------------------------
def draw_window(x, y):
global windows
windows = []
left = BLDG_LEFT + GAP + x* (WIN_SZ+GAP)
top = BLDG_TOP + GAP + y* (WIN_SZ+GAP)
r = Rectangle(Point( x *WIN_SZ+GAP, y *(WIN_SZ+GAP)),
Point((x+1)*WIN_SZ+GAP, (y+1)*(WIN_SZ+GAP)))
windows[x][y].append(r)
bit = randint(0,1)
windows[x][y].append(bool(bit))
windows[x][y][0].setFill(COLORS[bit])
windows[x][y][0].draw(win)
def draw_windows():
for i in range(WIN_FLR):
windows.append([])
for j in range(FLOORS):
windows[i].append([])
draw_window(i, j)
def office_tower():
global win
win = GraphWin("OFFICE TOWER", WIN_W, WIN_H)
draw_window(1, 1)
while True:
pt = win.getmouse()
if pt.x < 10 and pt.y < 10:
break
# windows coordinates
x = int((pt.x - BLDG_LEFT - GAP)/(WIN_SZ + GAP))
y = int((pt.y - BLDG_TOP - GAP)/(WIN_SZ + GAP))
print(str((pt.x, pt.y)) + ' --> ' + str((x, y)))
windows[x][y][1] = netwindows[x][y][1]
windows[x][y][0].setFill(COLORS[windows[x][y][1]])
def draw_building():
global windows
win = GraphWin("OFFICE TOWER", WIN_W, WIN_H)
N_H, N_V = 5, 10
while True:
pt = win.getMouse()
m_x, m_y = pt.getX(), pt.getY()
# Grid coordinates:
g_x = m_x // (WIN_W//N_H)
g_y = m_y // (WIN_H//N_V)
# For development purposes:
if m_x < 10 and m_y < 10:
break
This seems to be the worst virtual high-rise disaster since Irwin Allen's "Towering Inferno". There appear to be at least two different incomplete implementations in the file where most of the functions are never called and the code draws nothing. Here's my salvage job on the ruins:
from random import randint
from graphics import *
GRAPHIC_WINDOW_WIDTH, GRAPHIC_WINDOW_HEIGHT = 500, 400
# Top left coner of the building
BUILDING_LEFT, BUILDING_TOP = 50, 50
COLORS = ['gray25', 'gray85'] # lights off, lights on
# How many BUILDING_FLOORS, how many windows per floor, window size and gap
BUILDING_FLOORS, WINDOWS_PER_FLOOR, WINDOW_SIZE, WINDOW_GAP = 10, 5, 20, 5
WINDOW_FRAME = WINDOW_SIZE + WINDOW_GAP
# Syntax : window[x][y]
# [0] : Rectangle() object
# [1] : True/False
#--------------------------------------------------------------------
def draw_window(row, column, left, top):
r = Rectangle(Point(left + column * WINDOW_FRAME, top + row * WINDOW_FRAME), \
Point(left + (column + 1) * WINDOW_FRAME, top + (row + 1) * WINDOW_FRAME))
bit = bool(randint(0, 1))
r.setFill(COLORS[bit])
r.draw(win)
windows[row][column] = [r, bit]
def draw_windows(left, top):
for row in range(BUILDING_FLOORS):
windows.append([])
for column in range(WINDOWS_PER_FLOOR):
windows[row].append(None)
draw_window(row, column, left, top)
def office_tower():
draw_windows(BUILDING_LEFT, BUILDING_TOP)
while True:
pt = win.getMouse()
if pt.x < BUILDING_LEFT and pt.y < BUILDING_TOP:
break # clean exit stategy
# windows coordinates
column = int((pt.x - BUILDING_LEFT - WINDOW_GAP) / WINDOW_FRAME)
row = int((pt.y - BUILDING_TOP - WINDOW_GAP) / WINDOW_FRAME)
# print((pt.x, pt.y), '-->', (row, column))
windows[row][column][1] = not windows[row][column][1]
windows[row][column][0].setFill(COLORS[windows[row][column][1]])
win = GraphWin('OFFICE TOWER', GRAPHIC_WINDOW_WIDTH, GRAPHIC_WINDOW_HEIGHT)
windows = []
office_tower()
win.close()
This draws the following building:
Where you can click on the windows to toggle their color. (I chose an 'on' / 'off' motif.) Clicking to the upper left of the building exits.
I was trying to make an extension to a mcedit filter, originally by CrushedPixel, edited by NanoRex. That version they made doesn't support 1.9 snapshots / blocks, so I decided to make a better, lagless version that does!
Here's the code:
# MCEdit Filter by CrushedPixel
# http://youtube.com/CrushedPixel
# Heavily Modified by NanoRex
# Major bug (and some minor ones) fixed by NanoRex
# http://youtube.com/thecaptainrex7567
from pymclevel import TAG_List
from pymclevel import TAG_Byte
from pymclevel import TAG_Int
from pymclevel import TAG_Compound
from pymclevel import TAG_Short
from pymclevel import TAG_Double
from pymclevel import TAG_String
import math
from pymclevel import MCSchematic
import mcplatform
displayName = "JetDirectionsMod"
CmdBlockTypes = {
"Normal" : 137,
"Chain" : 211,
"Repeating" : 210,
}
CmdDataTypes = {
"Facing DOWN": 0,
"Facing UP": 1,
"Facing NORTH": 2,
"Facing SOUTH": 3,
"Facing WEST": 4,
"Facing EAST": 5,
}
DataKeys = ()
for key in CmdBlockTypes.keys():
DataKeys = DataKeys + (key,)
DataTypeKeys = ()
for key in CmdDataTypes.keys():
DataTypeKeys = DataTypeKeys + (key,)
inputs = (
("Placeholders: $rot | $mot | $dir","label"),
("Accuracy (Degrees)", (5,1,20)),
("Motion Factor", (0.1,9.0)),
("Set Position to In Front of Player:","label"),
("Placeholder: $pos","label"),
("Set Position", False),
("Distance From Player", (1,5)),
("Relative Y Position", (0,-1000,1000)),
("Command Block Type:", DataKeys),
("Commandblock Rotation:", DataTypeKeys),
)
def perform(level, box, options):
fac = options["Accuracy (Degrees)"]
speed = options["Motion Factor"]
adjustPos = options["Set Position"]
adjustAmount = options["Distance From Player"]
ypos = options["Relative Y Position"]
C = CmdBlockTypes[options["Command Block Type:"]]
D = CmdDataTypes[options["Commandblock Rotation:"]]
C = C, ' ', D
found = False
for x in xrange(box.minx,box.maxx):
if not found:
for y in xrange(box.miny,box.maxy):
if not found:
for z in xrange(box.minz,box.maxz):
te = level.tileEntityAt(x,y,z)
if te != None:
try:
text = te["Command"].value
found = True
break
except:
pass
commands = []
if not found:
raise Exception("Please select a command block in order to run this filter.")
for y in range(-90/fac,90/fac):
rxm = y*fac
rx = ((y+1)*fac)-1
if rx == 89 :
rx += 1
for x in range(-180/fac,180/fac):
rym = x*fac
ry = ((x+1)*fac)-1
if ry == 179 :
ry +=1
xdeg = math.radians(((x+1)*fac)-(fac/2))
ydeg = math.radians(((y+1)*fac)-(fac/2))
xmov = -speed*(math.sin(xdeg)*math.cos(ydeg))
ymov = -speed*math.sin(ydeg) + 0.1
zmov = speed*(math.cos(xdeg)*math.cos(ydeg))
cmd = text.replace("$rot", "rxm="+str(rxm)+",rx="+str(rx)+",rym="+str(rym)+",ry="+str(ry))
cmd = cmd.replace("$mot", "Motion:["+str(xmov)+","+str(ymov)+","+str(zmov)+"]")
cmd = cmd.replace("$dir", "direction:["+str(xmov)+","+str(ymov)+","+str(zmov)+"]")
if adjustPos == True :
if -67.5 < ((x+1)*fac)-(fac/2) < 67.5 :
zadj = adjustAmount
elif -180 <= ((x+1)*fac)-(fac/2) < -112.5 or 180 >= ((x+1)*fac)-(fac/2) > 112.5 :
zadj = -adjustAmount
else:
zadj = 0
if 22.5 < ((x+1)*fac)-(fac/2) < 157.5 :
xadj = -adjustAmount
elif -22.5 > ((x+1)*fac)-(fac/2) > -157.5 :
xadj = adjustAmount
else:
xadj = 0
cmd = cmd.replace("$pos", "~"+str(xadj)+" ~"+str(ypos)+" "+"~"+str(zadj))
commands.append(cmd)
number = len(commands)
size = math.sqrt(number/2)
rs = math.ceil(size)
if rs ** 2 > 4096 :
raise Exception("Too many command blocks for the /fill command. Increase \"Accuracy (Degrees)\" to solve this.")
schematic = MCSchematic((rs+2,4,rs+2), mats = level.materials)
i = 0
xc = 1
zc = -1
schematic.setBlockAt(1,3,0,210)
schematic.TileEntities.append(cmdBlockTe(1,3,0,"/fill ~ ~-2 ~1 ~"+str(int(rs))+" ~-2 ~"+str(int(rs+1))+" minecraft:redstone_block"))
schematic.setBlockAt(0,3,1,210)
schematic.TileEntities.append(cmdBlockTe(0,3,1,"/fill ~1 ~-2 ~ ~"+str(int(rs+1))+" ~-2 ~"+str(int(rs))+" minecraft:stone"))
for x in range(1, int(rs+2)):
xc += 1
for z in range(1, int(rs+2)):
zc += 1
y = 2
if i < number:
cmd = commands[i]
schematic.setBlockAt(x, y, z, C, D)
control = cmdBlockTe(x, y, z, cmd)
schematic.TileEntities.append(control)
i += 1
y = 0
if i < number:
cmd = commands[i]
schematic.setBlockAt(x, y, z, C)
control = cmdBlockTe(x, y, z, cmd)
schematic.TileEntities.append(control)
i += 1
zc = -1
schematic_file = mcplatform.askSaveFile(mcplatform.lastSchematicsDir or mcplatform.schematicsDir, "Save Schematic As...", "", "Schematic\0*.schematic\0\0", ".schematic")
if schematic_file == None:
print "ERROR: No schematic filename provided!"
return
schematic.saveToFile(schematic_file)
def cmdBlockTe(x,y,z,cmd):
control = TAG_Compound()
control["Command"] = TAG_String(cmd)
control["id"] = TAG_String(u'Control')
control["CustomName"] = TAG_String(u'#')
control["z"] = TAG_Int(z)
control["y"] = TAG_Int(y)
control["x"] = TAG_Int(x)
return control
This gives me the error: "Setting up an array element with senquence."
Here's some screens of what is this used to, and what's the problem:
Screen 1, Screen 2. Okay, so now I know what causes the problem. How can I solve it? I really want to get it working :l
C = C, ' ', D that creates a sequence, ie. something like (<Original C>, ' ', <Original D>), so when you're doing schematic.setBlockAt(x, y, z, C) your argument of C is a sequence, when it's expecting a single item.