caffe:how to concat two blobs after ImageData Layers - concatenation

I am trying to detect changed pixels from two images which are took in different time at the same place, so I used slice window to get 5x5 patches for every pixel in two images.
After that, I got 45000 patches for each image, and I selected 35000 patches randomly for training and the others for testing (two images use the same selection).
Then I stored in train/train1 and train/train2, val/val1 and val/val2.
The train1.txt looks like path/to/train/train1/1_00001.png 0,train2.txt looks like path/to/train/train2/2_00001.png 0,
1_00001 and 2_00001 are corresponding pixels in two images, and label=0 means unchanged, label=1 means changed, val1.txt and val2.txt are similar.
Instead of converting into lmdb or leveldb, I used ImageData Layer directly, after DataLayer,I aimed to concat two blobs in channel(the two images are single channel), so my train_val.prototxt is:
name: "ChangeDetec"
layer {
name: "data"
type: "ImageData"
top: "data"
top: "label"
include {
phase: TRAIN
}
transform_param {
scale: 0.00390625
}
image_data_param {
source: "data/changedetec/train1.txt"
batch_size: 500
}
}
layer {
name: "pair_data"
type: "ImageData"
top: "pair_data"
include {
phase: TRAIN
}
transform_param {
scale: 0.00390625
}
image_data_param {
source: "data/changedetec/train2.txt"
batch_size: 500
}
}
layer {
name: "data"
type: "ImageData"
top: "data"
top: "label"
include {
phase: TEST
}
transform_param {
scale: 0.00390625
}
image_data_param {
source: "data/changedetec/val1.txt"
batch_size: 1000
}
}
layer {
name: "pair_data"
type: "ImageData"
top: "pair_data"
include {
phase: TEST
}
transform_param {
scale: 0.00390625
}
image_data_param {
source: "data/changedetec/val2.txt"
batch_size: 1000
}
}
layer {
name: "channelconcat"
type: "Concat"
bottom: "data"
bottom: "para_data"
top: "concatdata"
}
layer {
name: "conv1/5x5"
type: "Convolution"
bottom: "concatdata"
top: "conv1/5x5"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 64
pad: 0
kernel_size: 5
stride: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
name: "conv1/relu_5x5"
type: "ReLU"
bottom: "conv1/5x5"
top: "conv1/5x5"
}
layer {
name: "conv2/1x1"
type: "Convolution"
bottom: "conv1/5x5"
top: "conv2/1x1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 64
kernel_size: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
name: "conv2/relu_1x1"
type: "ReLU"
bottom: "conv2/1x1"
top: "conv2/1x1"
}
layer {
name: "conv3/1x1"
type: "Convolution"
bottom: "conv2/1x1"
top: "conv3/1x1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 32
pad: 0
kernel_size: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
name: "conv3/relu"
type: "ReLU"
bottom: "conv3/1x1"
top: "conv3/1x1"
}
layer {
name: "conv4/1x1"
type: "Convolution"
bottom: "conv3/1x1"
top: "conv4/1x1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 16
pad: 0
kernel_size: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
name: "conv4/relu"
type: "ReLU"
bottom: "conv4/1x1"
top: "conv4/1x1"
}
layer {
name: "conv5/1x1"
type: "Convolution"
bottom: "conv4/1x1"
top: "conv5/1x1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 8
pad: 0
kernel_size: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
name: "conv5/relu"
type: "ReLU"
bottom: "conv5/1x1"
top: "conv5/1x1"
}
layer {
name: "conv6/1x1"
type: "Convolution"
bottom: "conv5/1x1"
top: "conv6/1x1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 4
pad: 0
kernel_size: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
name: "conv6/relu"
type: "ReLU"
bottom: "conv6/1x1"
top: "conv6/1x1"
}
layer {
name: "conv7/1x1"
type: "Convolution"
bottom: "conv6/1x1"
top: "conv7/1x1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 2
pad: 0
kernel_size: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
name: "conv7/relu"
type: "ReLU"
bottom: "conv7/1x1"
top: "conv7/1x1"
}
layers {
name: "pool"
bottom: "conv7/1x1"
top: "pool"
type: "Pooling"
pooling_param {
pool: AVE
kernel_size: 1
stride: 1
}
}
layer {
name: "accuracy"
type: "Accuracy"
bottom: "pool"
bottom: "label"
top: "accuracy"
include {
phase: TEST
}
}
layers {
name: "loss"
type: SoftmaxWithLoss
bottom: "pool"
bottom: "label"
top: "loss"
include: { phase: TRAIN }
}
and solver.prototxt is:
net: "examples/changedetec/train_val.prototxt"
test_iter: 500
test_interval: 500
base_lr: 0.001
lr_policy: "step"
gamma: 0.1
stepsize: 100000
display: 20
max_iter: 450000
momentum: 0.9
weight_decay: 0.0005
snapshot: 5000
snapshot_prefix: "examples/changedetec/changedetec_train"
solver_mode: GPU
But I got the error:
I0812 10:33:31.980985 3846 solver.cpp:91] Creating training net from net file: examples/changedetec/train_val.prototxt
[libprotobuf ERROR google/protobuf/text_format.cc:245] Error parsing text-format caffe.NetParameter: 11:11: Expected double.
F0812 10:33:31.981097 3846 upgrade_proto.cpp:79] Check failed: ReadProtoFromTextFile(param_file, param) Failed to parse NetParameter file: examples/changedetec/train_val.prototxt
*** Check failure stack trace: ***
# 0x7f148e770daa (unknown)
# 0x7f148e770ce4 (unknown)
# 0x7f148e7706e6 (unknown)
# 0x7f148e773687 (unknown)
# 0x7f148eecae3e caffe::ReadNetParamsFromTextFileOrDie()
# 0x7f148eedf17b caffe::Solver<>::InitTrainNet()
# 0x7f148eee024c caffe::Solver<>::Init()
# 0x7f148eee057a caffe::Solver<>::Solver()
# 0x7f148eea2043 caffe::Creator_SGDSolver<>()
# 0x40ed1e caffe::SolverRegistry<>::CreateSolver()
# 0x407ec2 train()
# 0x405cbc main
# 0x7f148d2cdf45 (unknown)
# 0x40648d (unknown)
# (nil) (unknown)
Aborted (core dumped)
What's wrong in my prototxts or is there something I did wrong?Has there a better way to tackle this problem?This has bothering me so many days,please help me.
update in Aug23
I have fixed some low-level errors and still get some other errors:
I commented scale:0.00390625 because the error says Error parsing text-format caffe.NetParameter: 11:11: Expected double..
Then the original error has been fixed,but the error jumped to Pooling layer,sayed Expected integer or identifier,so I commented Pooling layerand changed the last Convolution layer and ReLU layer's num_output to 2 when I use SoftmaxWithLoss layer,but the error is the same as Pooling layerexcept it happened in SoftmaxWithLoss layer.
I tried SigmoidCrossEntropyLoss with the last Convolution layer and ReLU layer's num_output is 1 but it makes no difference to the matter .
I also convert images into LMDB,but error just as well as 1-3 above.

Related

storybook argTypes control type

my interface:
interface TextProps {
w?: number | string;
h?: number | string;
}
my Text Component Style:
width: ${p => (typeof p.w === 'number' ? p.w + 'px' : p.w)};
height: ${p => (typeof p.h === 'number' ? p.h + 'px' : p.h)};
I want to 2 type(=string | number )in storybook argTypes...
export default {
title: 'Core/Text',
component: TextComponent,
argTypes: {
w: {}, // ?
h: {}, // ?
margin: { control: 'object', table: { type: { summary: 'array' } }, description: '텍스트 margin 간격' },
padding: { control: 'object', table: { type: { summary: 'array' } }, description: '텍스트 padding 간격' }
}
} as Meta;
help me :(
export default {
title: 'Core/Text',
component: TextComponent,
argTypes: {
w: { control: { type: ['string' | 'number'] }, table: { type: { summary: ['number', 'string'] } }, description: '텍스트 가로 사이즈' },
h: { control: ['string' | 'number'], table: { type: { summary: ['number', 'string'] } }, description: '텍스트 높이 사이즈' },
margin: { control: 'object', table: { type: { summary: 'array' } }, description: '텍스트 margin 간격' },
padding: { control: 'object', table: { type: { summary: 'array' } }, description: '텍스트 padding 간격' }
}
} as Meta;

How to edit an array inside another array in the useState of react

The purpose is to edit the position and size of a single target without the other data being affected
const [maps, setMap] = useLocalStorage('maps', [
{
id: 'map-1',
name: 'Producción',
settings: {
size: { width: 1500, height: 900 },
centerOnInit: false,
backgroundMap: '',
scaleOnInit: 0.9,
showSize: true,
},
targets: [
{
id: 0,
name: 'ITEM-0',
position: { x: 0, y: 0 },
image: 'https://cdn-icons-png.flaticon.com/512/1055/1055101.png',
size: { width: '50px', height: '50px' }
},
{
id: 1,
name: 'ITEM-1',
position: { x: 0, y: 0 },
image: 'https://cdn-icons-png.flaticon.com/512/1814/1814403.png',
size: { width: '50px', height: '50px' }
}
]
},
]);
If anyone could help it would be an immense help, thanks

Sum array of objects with Lodash

I'd like to sum objects from array, I've been searching and testing different things founds around there, using Lodash or not, without any success.
Here is the data array, there is 5 elements but it could be less or more. The properties will always be the same, but there could be a lot more.
const data = [
{
from: "2019-10-15",
stats: [
{
options: {
width: 15,
height: 20,
borders: 35,
removable: 5
}
}
]
},
{
from: "2019-10-16",
stats: [
{
options: {
width: 22,
height: 18,
borders: 10,
removable: 0
}
}
]
},
{
from: "2019-10-17",
stats: [
{
options: {
width: 0,
height: 15,
borders: 15,
removable: 0
}
}
]
},
{
from: "2019-10-18",
stats: [
{
options: {
width: 20,
height: 20,
borders: 10,
removable: 5,
}
}
]
},
{
from: "2019-10-19",
stats: [
{
options: {
width: 0,
height: 10,
borders: 0,
removable: 30
}
}
]
}
];
The expected result is the sum of each array element stats[0].options properties:
const sum = {
width: 57,
height: 83,
borders: 70,
removable: 40
}
I know it's definitely not complicated.
Use _.map() to get the options, then combine the objects using _.mergeWith(), and use _.add() as the customizer.
const data = [{"from":"2019-10-15","stats":[{"options":{"width":15,"height":20,"borders":35,"removable":5}}]},{"from":"2019-10-16","stats":[{"options":{"width":22,"height":18,"borders":10,"removable":0}}]},{"from":"2019-10-17","stats":[{"options":{"width":0,"height":15,"borders":15,"removable":0}}]},{"from":"2019-10-18","stats":[{"options":{"width":20,"height":20,"borders":10,"removable":5}}]},{"from":"2019-10-19","stats":[{"options":{"width":0,"height":10,"borders":0,"removable":30}}]}];
const result = _.mergeWith({}, ..._.map(data, 'stats[0].options'), _.add);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
If you use lodash/fp you can create a function using _.flow(), and replace _.mergeWith with _.mergeAllWith():
const { flow, map, mergeAllWith, add } = _;
const fn = flow(
map('stats[0].options'),
mergeAllWith(add)
);
const data = [{"from":"2019-10-15","stats":[{"options":{"width":15,"height":20,"borders":35,"removable":5}}]},{"from":"2019-10-16","stats":[{"options":{"width":22,"height":18,"borders":10,"removable":0}}]},{"from":"2019-10-17","stats":[{"options":{"width":0,"height":15,"borders":15,"removable":0}}]},{"from":"2019-10-18","stats":[{"options":{"width":20,"height":20,"borders":10,"removable":5}}]},{"from":"2019-10-19","stats":[{"options":{"width":0,"height":10,"borders":0,"removable":30}}]}];
const result = fn(data);
console.log(result);
<script src='https://cdn.jsdelivr.net/g/lodash#4(lodash.min.js+lodash.fp.min.js)'></script>
It can be done through vanill JavaScript. Just use reduce and foreach methods:
const data = [
{
from: "2019-10-15",
stats: [
{
options: {
width: 15,
height: 20,
borders: 35,
removable: 5
}
}
]
},
{
from: "2019-10-16",
stats: [
{
options: {
width: 22,
height: 18,
borders: 10,
removable: 0
}
}
]
},
{
from: "2019-10-17",
stats: [
{
options: {
width: 0,
height: 15,
borders: 15,
removable: 0
}
}
]
},
{
from: "2019-10-18",
stats: [
{
options: {
width: 20,
height: 20,
borders: 10,
removable: 5,
}
}
]
},
{
from: "2019-10-19",
stats: [
{
options: {
width: 0,
height: 10,
borders: 0,
removable: 30
}
}
]
}
];
const result = data.reduce((a, {stats}) => {
stats.forEach(({options}) => {
for (const key in options) {
a[key] = a[key] || 0;
a[key] += options[key];
}
});
return a;
}, {})
console.log(result);
The vanilla JS code looks like this:
const result = data.reduce((a, {stats}) => {
stats.forEach(({options}) => {
for (const key in options) {
a[key] = a[key] || 0;
a[key] += options[key];
}
});
return a;
}, {})
Another approach to do this with a reduce and nested forEach, but a bit more straightforward:
const data = [
{
from: "2019-10-15",
stats: [
{
options: {
width: 15,
height: 20,
borders: 35,
removable: 5
}
}
]
},
{
from: "2019-10-16",
stats: [
{
options: {
width: 22,
height: 18,
borders: 10,
removable: 0
}
}
]
},
{
from: "2019-10-17",
stats: [
{
options: {
width: 0,
height: 15,
borders: 15,
removable: 0
}
}
]
},
{
from: "2019-10-18",
stats: [
{
options: {
width: 20,
height: 20,
borders: 10,
removable: 5,
}
}
]
},
{
from: "2019-10-19",
stats: [
{
options: {
width: 0,
height: 10,
borders: 0,
removable: 30
}
}
]
}
];
let result = _.reduce(data, (acc, value) =>{
// our nested options object
const options = value.stats[0].options;
_.forEach(options, (optionValue, optionKey) =>{
// if we know about this key already, then add optionValue to it
// if not, this will be our first value for that key
acc[optionKey] = !!acc[optionKey] ? acc[optionKey] + optionValue : optionValue;
})
return acc;
}, {})
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>

custom ticks based on selected range from rangeSelector in Highstock

I am trying to get my Highcharts/Highstock chart to display a custom tick when the rangeSelector is set to All, I have it setup this way, but is throwing me errors when I try to use the interactive portion of the graph
Received below answer from Highstock Change tick interval on range selector change
componentDidMount() {
// Timezone Offset for PST standard is UTC timezone
Highcharts.setOptions({
global: {
timezoneOffset: 8 * 60
},
lang: {
thousandsSep: ','
}
});
Highcharts.stockChart('chart', {
chart: {
backgroundColor:'rgba(255, 255, 255, 0.0)',
height: 400,
zoomType: 'xy'
},
title: {
text: 'Bitcoin Chart',
style: {
color: 'white'
}
},
navigator: {
trigger: "navigator",
triggerOp: "navigator-drag",
rangeSelectorButton: undefined,
handles: {
backgroundColor: 'white',
borderColor: 'black'
}
},
scrollbar: {
enabled: false
},
rangeSelector: {
buttons: [{
type: 'day',
count: 1,
text: '1d'
}, {
type: 'day',
count: 7,
text: '7d'
}, {
type: 'month',
count: 1,
text: '1m'
}, {
type: 'month',
count: 3,
text: '3m'
}, {
type: 'year',
count: 1,
text: '1y'
}, {
type: 'all',
text: 'All'
}],
selected: 6,
// styles for the buttons
buttonTheme: {
fill: 'black',
// stroke: 'none',
'stroke-width': 0,
r: 8,
style: {
color: 'white',
fontWeight: 'bold'
},
states: {
hover: {
},
select: {
fill: 'white',
style: {
color: 'black'
}
}
}
},
// Date Selector box
inputBoxBorderColor: 'black',
inputBoxWidth: 120,
inputBoxHeight: 18,
inputStyle: {
color: 'black',
fontWeight: 'bold'
},
labelStyle: {
color: 'silver',
fontWeight: 'bold'
},
},
series: [{
name: 'Bitcoin Price',
color: 'black',
data: this.props.data.all_price_values,
type: 'area',
threshold: null,
tooltip: {
valuePrefix: '$',
valueSuffix: ' USD',
valueDecimals: 2
}
}],
plotOptions: {
series: {
fillColor: {
linearGradient: [0, 0, 0, 0],
stops: [
[0, '#FF9900'],
[1, Highcharts.Color(Highcharts.getOptions().colors[0]).setOpacity(0).get('rgba')]
]
}
}
},
xAxis: {
events: {
setExtremes: function(e) {
if (e.trigger === "rangeSelectorButton" && e.rangeSelectorButton.text === "All") {
var range = e.max - e.min;
// ticks spaced by one day or one hour
var ticksSpacing = range >= 86400 * 1000 ? 86400 : 3600;
this.update({
tickPositioner: function() {
var positions = [],
info = this.tickPositions.info;
for (var x = this.dataMin; x <= this.dataMax; x += ticksSpacing * 1000) { // Seconds * 1000 for ticks
positions.push(x);
};
positions.info = info;
return positions;
}
}, false);
}
}
},
title: {
enabled: true,
text: 'Date (Timezone: PST)',
style: {
color: 'white'
}
},
labels: {
style: {
color: 'white'
}
},
type: 'datetime',
dateTimeLabelFormats: {
day: '%b %e, %Y'
},
tickInterval: 1
},
yAxis: {
floor: 0,
labels: {
formatter: function () {
return '$' + this.axis.defaultLabelFormatter.call(this);
},
format: '{value:,.0f}',
align: 'left',
style: {
color: 'white'
},
},
},
// Mobile Design
responsive: {
rules: [{
condition: {
maxWidth: 600
},
chartOptions: {
chart: {
height: 400
},
subtitle: {
text: null
},
navigator: {
enabled: false
}
}
}]
}
});
}
I am talking about the blue highlighted section, when I move it, it throws an error
I am trying to get the charts to have 2 plots per day on ALL rangeSelector, displaying the first point in the day and the last point in a day. What am I doing wrong?
EDIT 1 : Updated to full config, X Axis is now being disrupted by the original answer, ticks on custom range selector is still in works. Added images to show what's going on
The setExtremes event is raised each time you change the range to be displayed on the graph. It can have several origins:
A button click in the range selector
An handle drag in the navigator
etc..
The actual properties of the event depend on its origin. If you output the event with console.log(e), you'll see that it's not the same for these two origins:
Button click in the range selector
{
trigger: "rangeSelectorButton",
rangeSelectorButton: {
text: "2Hour",
type: "hour",
count: 2,
},
...
}
Handle drag in the navigator
{
trigger: "navigator",
triggerOp: "navigator-drag",
rangeSelectorButton: undefined
}
If you drag the handle in the navigator, there's no rangeSelectorButton attached to the event, because it doesn't make sense: in that case, no button is pressed.
To fix your error, you can add a check on the trigger property:
xAxis: {
events: {
setExtremes: function(e) {
if (e.trigger === "rangeSelectorButton" && e.rangeSelectorButton.text === "All") {
...
}
}
}
How to solved the actual issue
Now, the REAL issue. You want to change the ticks based on what is displayed: either the beginning and end of each day, or hours if not a complete day. You can do that with e.min and e.max, that represent the selected time range.
Like so:
setExtremes: function(e) {
var range = e.max - e.min;
// ticks spaced by one day or one hour
var ticksSpacing = range >= 86400 * 1000 ? 86400 : 3600;
this.update({
tickPositioner: function() {
var positions = [],
info = this.tickPositions.info;
for (var x = this.dataMin; x <= this.dataMax; x += ticksSpacing * 1000) { // Seconds * 1000 for ticks
positions.push(x);
};
positions.info = info;
return positions;
}
}, false);
}

Jointjs and angular : ng click doesn't work

I am creating an element with joint js and putting it inside a paper. The element has an ng-click directive in a pencil. However when I click on the element
The element
joint.shapes.flowie.Rect = joint.shapes.basic.Generic.extend(_.extend({}, joint.shapes.basic.PortsModelInterface, {
markup: '<g class="rotatable" ><g class="scalable"><rect class="body"/></g><text class="label"/><text region="" transform="translate(40,10)" ng-init="alert()" ng-click="loadStep(workflow.steps[this.stepName])" class="fa edit fa-pencil"></text><g class="inPorts"/><g class="outPorts"/></g>',
portMarkup: '<g class="port port<%= id %>"><circle class="port-body"/><text class="port-label"/></g>',
defaults: joint.util.deepSupplement({
type: 'devs.Model',
size: { width: 1, height: 1 },
inPorts: [],
outPorts: [],
attrs: {
'.': { magnet: false },
'.body': {
width: 150, height: 350,
stroke: '#000000'
},
'.port-body': {
r: 8,
magnet: true,
stroke: '#000000'
},
text: {
// 'pointer-events': 'none'
},
'.label': { text: 'Model', 'ref-x': .5, 'ref-y': 10, ref: '.body', 'text-anchor': 'middle', fill: '#000000' },
'.inPorts .port-label': { x:-15, dy: 4, 'text-anchor': 'end', fill: '#000000'},
".inPorts circle": {type:"input", magnet:"passive" },
'.outPorts .port-label':{ x: 15, dy: 4, fill: '#000000',type:"output" }
}
}, joint.shapes.basic.Generic.prototype.defaults),
getPortAttrs: function(portName, index, total, selector, type) {
var attrs = {};
var portClass = 'port' + index;
var portSelector = selector + '>.' + portClass;
var portLabelSelector = portSelector + '>.port-label';
var portBodySelector = portSelector + '>.port-body';
attrs[portLabelSelector] = { text: portName };
attrs[portBodySelector] = { port: { id: portName || _.uniqueId(type) , type: type } };
attrs[portSelector] = { ref: '.body', 'ref-y': (index + 0.5) * (1 / total) };
if (selector === '.outPorts') { attrs[portSelector]['ref-dx'] = 0; }
return attrs;
}
}));
There is a saveStep function triggered by saving a form. The form contains some metadata for each element
I then do the following to add the step to the graph
shape = new joint.shapes.flowie.Start({
position: { x: 10, y: 10 },
size: { width: 100, height: 30 },
attrs: { rect: { fill: 'blue' }, '.label': { text: step.stepName, fill: 'white' } },
stepName:name
});
shape.set('inPorts', []);
shape.set('outPorts', ['OUT']);
graph.addCells([shape])
I have heard of the compile directive but can't figure out a way to use it.

Resources