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.