mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
Add copy color.
The copy color function now works. It will automatically determine the best thresholds to use to track a particular color blob for you.
This commit is contained in:
parent
cf71b75962
commit
97a456c837
@ -100,6 +100,7 @@ Kwabena W. Agyeman</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Copy Color</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="activate" handler="on_copy_color_activate" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
@ -342,7 +343,7 @@ Kwabena W. Agyeman</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_STRUCTURE_MASK</property>
|
||||
<property name="title" translatable="yes">OpenMV IDE</property>
|
||||
<property name="default_width">800</property>
|
||||
<property name="default_width">1024</property>
|
||||
<property name="default_height">600</property>
|
||||
<signal name="destroy" handler="on_top_window_destroy" swapped="no"/>
|
||||
<child>
|
||||
|
||||
@ -11,6 +11,7 @@ from os.path import expanduser
|
||||
import gtksourceview2 as gtksourceview
|
||||
from glob import glob
|
||||
import urllib2, json
|
||||
import numpy as np
|
||||
|
||||
#import pydfu on Linux
|
||||
if platform.system() == "Linux":
|
||||
@ -123,6 +124,26 @@ class OMVGtk:
|
||||
sourceview.set_auto_indent(True)
|
||||
sourceview.set_highlight_current_line(True)
|
||||
|
||||
fonts = []
|
||||
for font in sourceview.get_pango_context().list_families():
|
||||
fonts.append(font.get_name().lower())
|
||||
|
||||
if sys.platform.startswith("win"):
|
||||
if "consolas" in fonts:
|
||||
sourceview.modify_font(pango.FontDescription("consolas 10"))
|
||||
else:
|
||||
sourceview.modify_font(pango.FontDescription("courier new 10"))
|
||||
elif sys.platform.startswith("darwin"):
|
||||
if "monaco" in fonts:
|
||||
sourceview.modify_font(pango.FontDescription("monaco 10"))
|
||||
else:
|
||||
sourceview.modify_font(pango.FontDescription("courier new 10"))
|
||||
elif sys.platform.startswith("linux"):
|
||||
if "dejavu sans mono" in fonts:
|
||||
sourceview.modify_font(pango.FontDescription("dejavu sans mono 10"))
|
||||
else:
|
||||
sourceview.modify_font(pango.FontDescription("courier new 10"))
|
||||
|
||||
# configure gtksourceview buffer
|
||||
self.buffer = gtksourceview.Buffer()
|
||||
self.buffer.set_highlight_syntax(True)
|
||||
@ -173,6 +194,7 @@ class OMVGtk:
|
||||
"on_save_file_as" : self.save_file_as,
|
||||
"on_about_dialog" : self.about_dialog,
|
||||
"on_pinout_dialog" : self.pinout_dialog,
|
||||
"on_copy_color_activate" : self.copy_color,
|
||||
"on_save_template_activate" : self.save_template,
|
||||
"on_save_descriptor_activate" : self.save_descriptor,
|
||||
"on_ctrl_scale_value_changed" : self.on_ctrl_scale_value_changed,
|
||||
@ -196,7 +218,7 @@ class OMVGtk:
|
||||
# set config parser
|
||||
self.config = configparser.ConfigParser()
|
||||
|
||||
config_valid = True
|
||||
config_valid = True
|
||||
|
||||
# check if config file exists
|
||||
if os.path.isfile(CONFIG_PATH):
|
||||
@ -306,7 +328,7 @@ class OMVGtk:
|
||||
return
|
||||
|
||||
# Set higher timeout after connecting for lengthy transfers.
|
||||
openmv.set_timeout(2)
|
||||
openmv.set_timeout(1*2) # SD Cards can cause big hicups.
|
||||
|
||||
# add terminal update callback
|
||||
gobject.gobject.timeout_add(30, omvgtk.update_terminal)
|
||||
@ -701,6 +723,127 @@ class OMVGtk:
|
||||
with open(self.file_path, "w") as file:
|
||||
file.write(self.buffer.get_text(self.buffer.get_start_iter(), self.buffer.get_end_iter()))
|
||||
|
||||
def copy_color(self, widget):
|
||||
self.da_menu.hide()
|
||||
x = self.x1
|
||||
y = self.y1
|
||||
w = self.x2-self.x1
|
||||
h = self.y2-self.y1
|
||||
|
||||
def rgb2lab(rgb):
|
||||
|
||||
def lin(c):
|
||||
return 100 * ((c/12.92) if (c<=0.04045) else pow((c+0.055)/1.055, 2.4))
|
||||
|
||||
def f(t):
|
||||
return pow(t, (1/3.0)) if (t>0.008856) else ((7.787037*t)+0.137931)
|
||||
|
||||
r_lin = lin(rgb[0] / 255.0)
|
||||
g_lin = lin(rgb[1] / 255.0)
|
||||
b_lin = lin(rgb[2] / 255.0)
|
||||
|
||||
x = (r_lin * 0.4124) + (g_lin * 0.3576) + (b_lin * 0.1805);
|
||||
y = (r_lin * 0.2126) + (g_lin * 0.7152) + (b_lin * 0.0722);
|
||||
z = (r_lin * 0.0193) + (g_lin * 0.1192) + (b_lin * 0.9505);
|
||||
|
||||
x = f(x / 095.047)
|
||||
y = f(y / 100.000)
|
||||
z = f(z / 108.883)
|
||||
|
||||
l = int(round(116 * y)) - 16;
|
||||
a = int(round(500 * (x-y)));
|
||||
b = int(round(200 * (y-z)));
|
||||
|
||||
return (l, a, b)
|
||||
|
||||
def rgb2gry(rgb):
|
||||
|
||||
def lin(c):
|
||||
return 100 * ((c/12.92) if (c<=0.04045) else pow((c+0.055)/1.055, 2.4))
|
||||
|
||||
def f(t):
|
||||
return (1.055*pow(t, (1/2.4)))-0.055 if (t>0.0031308) else 12.92*t
|
||||
|
||||
r_lin = lin(rgb[0] / 255.0)
|
||||
g_lin = lin(rgb[1] / 255.0)
|
||||
b_lin = lin(rgb[2] / 255.0)
|
||||
|
||||
y = f(((r_lin * 0.2126) + (g_lin * 0.7152) + (b_lin * 0.0722)) / 100.0);
|
||||
return max(min(y * 255, 255), 0)
|
||||
|
||||
def stats(buf, f):
|
||||
new_buf = np.zeros((buf.shape[0], buf.shape[1]), int)
|
||||
hist = np.zeros(384, int)
|
||||
for i in range(buf.shape[0]):
|
||||
for j in range(buf.shape[1]):
|
||||
color = f(buf[i][j])
|
||||
new_buf[i][j] = color
|
||||
hist[color + 128] += 1
|
||||
return (np.mean(new_buf),
|
||||
np.median(new_buf),
|
||||
np.argmax(hist) - 128,
|
||||
np.std(new_buf),
|
||||
np.amin(new_buf),
|
||||
np.amax(new_buf),
|
||||
np.percentile(new_buf, 25),
|
||||
np.percentile(new_buf, 75))
|
||||
|
||||
buf = self.pixbuf.subpixbuf(x, y, w, h).get_pixels_array()
|
||||
r_stats = stats(buf, lambda x: x[0])
|
||||
g_stats = stats(buf, lambda x: x[1])
|
||||
b1stats = stats(buf, lambda x: x[2])
|
||||
l_stats = stats(buf, lambda x: rgb2lab(x)[0])
|
||||
a_stats = stats(buf, lambda x: rgb2lab(x)[1])
|
||||
b2stats = stats(buf, lambda x: rgb2lab(x)[2])
|
||||
y_stats = stats(buf, lambda x: rgb2gry(x))
|
||||
out = [r_stats, g_stats, b1stats, l_stats, a_stats, b2stats, y_stats]
|
||||
|
||||
rgb_thresholds = [max(r_stats[6] - r_stats[3]*3, 0),
|
||||
min(r_stats[7] + r_stats[3]*3, 255),
|
||||
max(g_stats[6] - g_stats[3]*3, 0),
|
||||
min(g_stats[7] + g_stats[3]*3, 255),
|
||||
max(b1stats[6] - b1stats[3]*3, 0),
|
||||
min(b1stats[7] + b1stats[3]*3, 255)]
|
||||
lab_thresholds = [max(l_stats[6] - l_stats[3]*3, 0),
|
||||
min(l_stats[7] + l_stats[3]*3, 100),
|
||||
max(a_stats[6] - a_stats[3]*3, -128),
|
||||
min(a_stats[7] + a_stats[3]*3, 127),
|
||||
max(b2stats[6] - b2stats[3]*3, -128),
|
||||
min(b2stats[7] + b2stats[3]*3, 127)]
|
||||
gry_thresholds = [max(y_stats[6] - y_stats[3]*3, 0),
|
||||
min(y_stats[7] + y_stats[3]*3, 255)]
|
||||
out.extend([rgb_thresholds, lab_thresholds, gry_thresholds])
|
||||
|
||||
self.buffer.begin_user_action()
|
||||
iter = self.buffer.get_iter_at_mark(self.buffer.get_mark("insert"))
|
||||
iter.forward_line()
|
||||
self.buffer.insert(iter,\
|
||||
"# = RGB Color Space Stats ========================\n"\
|
||||
"# R: Mean %4d, Median %4d, Mode %4d, Stdev %4d\n"\
|
||||
"# Min %4d, Max %4d, LQ %4d, UQ %4d\n"\
|
||||
"# G: Mean %4d, Median %4d, Mode %4d, Stdev %4d\n"\
|
||||
"# Min %4d, Max %4d, LQ %4d, UQ %4d\n"\
|
||||
"# B: Mean %4d, Median %4d, Mode %4d, Stdev %4d\n"\
|
||||
"# Min %4d, Max %4d, LQ %4d, UQ %4d\n"\
|
||||
"# = LAB Color Space Stats ========================\n"\
|
||||
"# L: Mean %4d, Median %4d, Mode %4d, Stdev %4d\n"\
|
||||
"# Min %4d, Max %4d, LQ %4d, UQ %4d\n"\
|
||||
"# A: Mean %4d, Median %4d, Mode %4d, Stdev %4d\n"\
|
||||
"# Min %4d, Max %4d, LQ %4d, UQ %4d\n"\
|
||||
"# B: Mean %4d, Median %4d, Mode %4d, Stdev %4d\n"\
|
||||
"# Min %4d, Max %4d, LQ %4d, UQ %4d\n"\
|
||||
"# = GRY Color Space Stats ========================\n"\
|
||||
"# Mean %4d, Median %4d, Mode %4d, Stdev %4d\n"\
|
||||
"# Min %4d, Max %4d, LQ %4d, UQ %4d\n"\
|
||||
"# = Suggested Thresholds (LQ-Stdev*3, UQ+Stdev*3) \n"\
|
||||
"# Use LAB for RGB565 and GRY for GRAYSCALE images.\n"\
|
||||
"# RGB = (%4d, %4d, %4d, %4d, %4d, %4d)\n"\
|
||||
"# LAB = (%4d, %4d, %4d, %4d, %4d, %4d)\n"\
|
||||
"# GRY = (%4d, %4d)\n"\
|
||||
"# ================================================\n"\
|
||||
% tuple([i for sub in out for i in sub]))
|
||||
self.buffer.end_user_action()
|
||||
|
||||
def save_template(self, widget):
|
||||
self.da_menu.hide()
|
||||
x = self.x1
|
||||
|
||||
Loading…
Reference in New Issue
Block a user