I am implementing hybrid image with ImageJ and stuck at merging low filter image and high filter image to form a hybrid image.
This is what I already done.I have 2 images from Gaussian Blur and Laplician of Gaussian filer. I need to merge these 2 images by layer after that. Any idea how to achieve it?
import ij.*;
import ij.process.*;
import ij.gui.*;
import java.awt.*;
import ij.plugin.filter.*;
import ij.plugin.*;
import ij.io.*;
import java.io.*;
public class HybridImage_Plugin implements PlugInFilter{
int cfsize=3;
String img_lowPass;
String img_highPass;
private double[][] filter;
private double sigma;
float w=2 ,delta=0 , thr=0;
int mode=0;
//dialogbox
private boolean GUI()
{
GenericDialog gd = new GenericDialog("Enter Values", IJ.getInstance());
gd.addNumericField("Sigma (3,5,9,17,35)", cfsize, 0);
gd.addStringField("Low-Pass", "/home/atrx/ImageJ/plugins/hybridimage/l1.tif");
gd.addStringField("High-Pass", "/home/atrx/ImageJ/plugins/hybridimage/l2.tif");
return getUserParams(gd);
}
//get parameters
private boolean getUserParams(GenericDialog gd)
{
gd.showDialog();
if (gd.wasCanceled())
{
return false;
}
cfsize = (int) gd.getNextNumber();
img_lowPass = gd.getNextString();
img_highPass= gd.getNextString();
return true;
}
public int setup(String arg, ImagePlus imp) {
return PlugInFilter.NO_IMAGE_REQUIRED;
}
public void run(ImageProcessor ip) {
int[][] result;
if(GUI() == false)
{
return;
}
else
{
Opener opener1 = new Opener();
Opener opener2 = new Opener();
ImagePlus imp1= opener1.openImage(img_lowPass);
ImagePlus imp2= opener2.openImage(img_highPass);
//imp1.show("Low Pass Image");
//imp2.show("HighPass Image");
ImageProcessor ip1 = imp1.getProcessor();
ImageProcessor ip2 = imp2.getProcessor();
//lowpass filter(Gaussian Blur)
ip1.blurGaussian(cfsize);
showProcessor(ip1,"Low Pass Filtered Image");
//highpass filter(LoG)
int csize = ip2.getHeight();
int rsize = ip2.getWidth();
Rectangle rect = ip2.getRoi();
int d0,a0,acr,dow,it;
int i,x,y;
double h12, h21, ft, h1h2, h2h1, fmu, dh, dv;
double r, dt, dmx, dmn;
float logaus[] = new float[(rect.width>rect.height)? rect.width : rect.height];
float gaus[] = new float[(rect.width>rect.height)? rect.width : rect.height];
float dgaus[] = new float[(rect.width>rect.height)? rect.width : rect.height];
long zcn =0;
byte pixels[] = (byte[])ip2.getPixels();
int img_in[] = new int[rect.width*rect.height];
if (cfsize<0) cfsize=3;
if (cfsize>35) cfsize=35;
if(w<0) w=0;
int fsize = (int)(cfsize*w);
if (fsize%2 == 0)
{
fsize += 1;
}
double dimg[] = new double[rect.height*rect.width];
double dr[] = new double[rect.height*rect.width];
i=0;
for(y=rect.y;y<(rect.y+rect.height);y++)
{
for(x=rect.x;x<(rect.x+rect.width);x++)
{
img_in[i] = (pixels[(y*rsize)+x]&0xff);
i++;
}
}
int size = rect.width + fsize -1;
int image[] = new int[(rect.width+fsize-1)*(rect.height+fsize-1)];
int extension= (fsize/2);
for( i=0; i<rect.height;i++)
{
System.arraycopy(img_in,(i*rect.width),image,( ((i+extension)*(rect.width+fsize-1))+ extension ),rect.width);
}
h1h2= h2h1 = h12 =0.0;
for(i=1; i<( (fsize+1) /2);i++)
{
w = (float)cfsize/(float)2.0/(float)1.414;
ft = i/w;
gaus[i] = (float)Math.exp(-ft*ft/2);
h1h2 += 2.0 *(gaus[i]);
logaus[i] =(float)(1-ft*ft)*(float)Math.exp(-ft*ft/2);
h2h1 += 2.0*(logaus[i]);
dgaus[i] =(float)ft*(float)Math.exp(-ft*ft/2);
}
fmu = (h2h1 + 1)* (h1h2+1);
int prel[] = new int[rect.width+1];
dmx = -99999.9;
dmn = 99999.9;
int limit = ((rect.width+fsize-1)*(rect.height+fsize-1));
for(d0=0;d0<rect.height;d0++)
{
for(a0=0;a0<rect.width;a0++)
{
acr = a0 + fsize/2;
dow = d0 + fsize/2;
dh = dv = 0.0;
h1h2 = h2h1 = 0.0;
for (int j=1; j<(fsize+1)/2; j++)
{
int a0d0, a0d1, a1d0, a1d1;
h12=h21=0.0;
for(i=1;i<(fsize+1)/2;i++)
{
a0d0 = acr-i+((dow-j)*size);
a0d1 = acr-i+((dow+j)*size);
a1d0 = acr+i+((dow-j)*size);
a1d1 = acr+i+((dow+j)*size);
h12 += logaus[i]*(image[a0d0] + image[a0d1]+
image[a1d0] + image[a1d1]);
h21 += gaus[i]* (image[a0d0] + image[a0d1] +
image[a1d0] + image[a1d1]);
}
a0d0 = acr-j+dow*size;
a0d1 = acr+(dow-j)*size;
a1d0 = acr+j+dow*size;
a1d1 = acr+(dow+j)*size;
h1h2 += gaus[j] * (h12+ image[a0d0]+image[a0d1]+
image[a1d0]+image[a1d1]);
h2h1 += logaus[j]*(h21+ image[a0d0]+ image[a0d1] +
image[a1d0] + image[a1d1] );
if(thr != 0.0)
{
dh += dgaus[j] * ( image[a1d0] - image[a0d0] );
dv += dgaus[j] * ( image[a1d1] - image[a0d1] );
}
}
dt = dimg[d0*rect.width+a0] = h1h2 + h2h1 + (2*image[dow*size+acr]) ;
if (dt > dmx) dmx = dt;
if (dt < dmn) dmn = dt;
if( thr!= 0.0)
{
dr[(d0*rect.width)+a0] = Math.abs(dh) + Math.abs(dv);
}
}
}
dmx = (dmx-dmn) / 2;
dmn += dmx;
int row=0, column=0;
for(d0=0;d0<rect.height;d0++)
{
for(a0=0;a0<rect.width;a0++)
{
int id = (d0*rect.width) +a0;
int index = rsize*(rect.y+d0) + (a0+rect.x);
int k = 15;
it = (int)(dt = (dimg[id] - (dmn-delta*dmx))*255 / (dmx*(1+Math.abs(delta))));
switch(mode){
case 0:
pixels[index] = (byte)((dt-dmn+dmx)/dmx*127);
break;
case 1:
pixels[index] = (byte)Math.abs(it);
break;
case 2:
pixels[index] = (byte)( ((dt!=0)?((dt>0) ? 1: -1) : 0) * 192);
break;
case 3:
default:
r = dr[id];
it = ( (dt!=0) ? ((dt>0) ? 1: -1) : 0);
if( it==0 && r>=thr)
{
k = 255;
zcn++;
}
else
{
if( (it*prel[a0]<0 || it*prel[a0+1]<0) && r>=thr)
{
k = 255;
zcn++;
}
}
prel[a0+1] = it;
if(k==255 || mode!=3)
pixels[index] = (byte)k;
break;
}
}
}
showProcessor(ip2,"High Pass Filtered Image");
}
}
static void showProcessor(ImageProcessor ip, String title){
ImagePlus win = new ImagePlus(title,ip);
win.show();
}
}
Have you tried performing a weighted sum?
OUT = w*LPF + (1 - w)*HPF
This kind of sum is used everywhere. In particular, image blending, alpha matting and even in some optimization schemes.
However because there are patches of varying spatial frequencies all around your image, you may have to make the weight adaptive. You also have to choose which one you want to emphasize more. Do you want the low pass or high pass information to stand out more? Depending on which you want, you might want to use information in either one of those images and run it through some distance or similarity measure to get the right weight.
Related
I create alist method to insert principal values and remaining balances according to the payments.But when I implement this method in actionListner method error occurs(EventDispatchThread Execption).I try to solve it.Please give any help for me to solve this.
public class Loan {
float lamt,irate,inst,lbalance;
int duration,nop;
String amtlist[][] = new String[duration+1][5];
Loan(float lamt, float irate, int duration, int nop) {
this.lamt = lamt;
this.irate = irate;
this.duration = duration;
this.nop = nop;
}
public void alist() {
amtlist[0][0] = "0" ;
amtlist[0][1] = "0";
amtlist[0][2] = "0";
amtlist[0][3] = "0";
amtlist[0][4] = Float.toString(inst*annuity(duration,irate));
float v = 1 / (1 + irate);
for (int i = 1; i < duration + 1; i++) {
amtlist[i][0] = Float.toString(i);
amtlist[i][1] = Float.toString(irate * annuity(duration + 1 - i, irate));
amtlist[i][2] = Float.toString(instalment());
amtlist[i][3] = Double.toString(instalment() * Math.pow(v, i));
amtlist[i][4] = Float.toString(instalment() * annuity(duration - i, irate));
}
}
public float annuity(int duration, float irate) {
float v = 1 / (1 + irate);
float an = (float) ((1 - Math.pow(v, duration)) / irate);
return an;
}
public float instalment(){
return inst = lamt / annuity(duration, irate);
}
public float lbalance() {
return lbalance = inst * annuity(duration - nop, irate);
}
}
public void actionPerformed(ActionEvent e) {
String lamtstr = tf1.getText();
String iratestr = tf2.getText();
String durationstr = tf3.getText();
String nopstr = tf4.getText();
float lamt = Float.parseFloat(lamtstr);
float irate = Float.parseFloat(iratestr);
int duration = Integer.parseInt(durationstr);
int nop = Integer.parseInt(nopstr);
Loan l = new Loan(lamt, irate, duration, nop);
float inst = 0, balance = 0;
if (e.getSource() == b1) {
inst =l.instalment();
balance =l.lbalance();
}
if (e.getSource() == b2) {
l.alist();
fscr.dispose();
new AmTable(l.amtlist);
}
tf5.setText(String.valueOf(inst));
tf6.setText(String.valueOf(balance));
}
I tried solve it by changing alist method to value returning method but my attempt got vain.
if (e.getSource() == b2) {
l.alist();
fscr.dispose();
new AmTable(l.amtlist);
}
I expected to call AmTable function with amlist array.
Good afternoon, I am using stm32 Blue Pill on USB raised com - port, development environment "IAR".
The problem is the following, when I connect through the application, the number "3"
does not change to the number "50" after the arrow, but on the contrary is shown next !
See Figure 1.2. I work under the protocol.
How do you achieve this?
I'm using the controlP5 library and cp5.addNumberbox.
Data in "IAR".
int Bullet = 50; // variable for result
sprintf((char *)str, "(,%d,-Ђ",Bullet); // sending a command with data to stm32.
In the code of the Displaydata tab, the line "case 40" is the symbol (
The command can also be sent through the terminal using a virtual com port.
Command: (, 50 ,! Figure 3.
I'll have to lay out the whole little project for you to check it out.
Com_Interface1:
import processing.serial.*;
import controlP5.*;
ControlP5 cp5;
DropdownList serialPortsList;
Serial serialPort;
final int BAUD_RATE = 9600;
char parity = 'N';
int dataBits = 8;
float stopBits = 1.0;
public void setup() {
background(50);
size(700, 420, P3D);
surface.setTitle("TEST");
surface.setResizable(false);
setupUI();
smooth();
frameRate(30);
writeOutgioing[lengthmas-1]=1;
String[] portNames = Serial.list();
//serialPort.clear(); // Why does not it work?
for (int i = 0; i < portNames.length; i++) serialPortsList.addItem(portNames[i], i);
}
public void toplug (int theValue)
{ // Start button on click sends a commad 1.
println("Button click events: "+theValue);
strata =!strata;
if (!strata) {
connection.setLabel("Пуск");
serialPort.dispose();
Vin.setText("Voltage K.V - ");
inputPULI.setLabel("Bullet");
} else {
connection.setLabel("СТОП");
serialports((int)serialPortsList.getValue());
writeOutgioing[0]=1;
writeOut();
}
}
public void serialports(int theValue) {
try {
serialPort = new Serial(this, Serial.list()[theValue], BAUD_RATE, parity, dataBits, stopBits);
serialPort.bufferUntil('\n');
println("COM connected: "+ Serial.list()[theValue] );
/*Send.unlock();
connection.unlock();*/ // locking buttons in applications if not connected via rs-232.
}
catch(Exception e) {
System.err.println("Error opening serial port" + Serial.list()[theValue]);
e.printStackTrace();
}
}
/*void controlEvent(ControlEvent event){
println(event.getController().getName(),"changed value to",event.getValue(),"inputPULI = ",PUL,"inputNapryzenieKV = ",NapryzenieKV,"CheckBoxuvum= ",
UV/UM,"P4 = ",std2,);
}*/
Displaydata:
void Displaydata() {
switch(x)
{
case 20:
// What to write?
// label(testRead[1]+" Мин."); // ImageButton
// min=testRead[1];
break;
case 30:
// What to write?
// P4.setText("std2"+ testRead[1]); // CheckBox
break;
case 40:
inputPULI.setLabel("Bullet: " + testRead[1] );
break;
case 70:
inputNapryzenieKV.setLabel("Voltage: " + testRead[1] );
break;
case 60:
Vin.setText("Voltage K.V: " + testRead[1] + " " + testRead[2]);
break;
case 50:
// What to write?
//CheckBoxuvum.setText("UV/UM - " +testRead[1] ); // RadioButton
break;
default:
println("DisplayData(): no case selected.");
break; // technically not necessary, but I like my switches tidy
}
}
GUI:
int PUL;
float NapryzenieKV;
boolean strata=false;
ImageButton button;
Numberbox inputPULI;
Numberbox inputNapryzenieKV;
RadioButton CheckBoxuvum;
CheckBox P4;
Textlabel Vin;
Button connection;
Button Send;
public void setupUI()
{
cp5 = new ControlP5(this);
PFont fontn = createFont("Times New Roman", 18);
PFont p = createFont("Times New Roman", 18);
ControlFont font=new
ControlFont(p);
cp5.setFont(font);
connection = cp5.addButton("toplug")
.setCaptionLabel("ПУСК")
.setPosition(387, 30)
.setSize(150, 30);
serialPortsList = cp5.addDropdownList("Порт")
.setPosition(130, 30)
.setSize(150, 200)
.setItemHeight(30)
.setBarHeight(30);
PImage[] imgs = {loadImage("button101.png"), loadImage("button102.png"), loadImage("button103.png")};
Send = cp5.addButton("toapply")
//.setCaptionLabel("Apply")
//.setPosition(510, 370)
//.setSize(150, 30);
.setPosition(590, 330)
.setImages(imgs)
.updateSize();
//.lock()
Vin = cp5.addTextlabel("naprazhenie kondencatora")
.setText("Voltage K.V")
.setFont(p)
.setColor(color(#00ffff))
.setPosition(45, 320);
CheckBoxuvum = cp5.addRadioButton("UV/UM")
.setPosition(155, 360)
.setSize(15, 15)
.setColorActive(color(255))
.setItemsPerRow(2)
.setSpacingColumn(85)
.addItem("+", 1)
.addItem("-", 2);
P4 = cp5.addCheckBox("std2")
.setPosition(150, 190)
.setSize(15, 15)
.setItemsPerRow(1)
.setSpacingColumn(30)
.setSpacingRow(20)
.addItem("Check", 2);
inputPULI = cp5.addNumberbox("PUL")
.setLabel("Bullet")
.setPosition(220, 220)
.setSize(80, 30)
.setColorValue(0xffffff00)
.setFont(p)
.setScrollSensitivity(1.1)
.setDirection(Controller.HORIZONTAL)
.setRange(1, 199)
.setValue(3);
Label labelinputPULI = inputPULI.getCaptionLabel();
labelinputPULI.setFont(font);
labelinputPULI.setColor(color(#00ffff));
labelinputPULI.toUpperCase(false);
labelinputPULI.setText("Bullet");
labelinputPULI.align(ControlP5.LEFT_OUTSIDE, CENTER);
labelinputPULI.getStyle().setPaddingLeft(-25);
inputNapryzenieKV = cp5.addNumberbox("NapryzenieKV")
.setLabel("Voltage")
.setPosition(150, 270)
.setSize(80, 30)
.setColorValue(0xffffff00)
.setFont(p)
.setScrollSensitivity(1.1)
.setMin(25)
.setMax(99)
.setMultiplier(0.01)
.setDirection(Controller.HORIZONTAL)
.setValue(25);
Label labelinputNapryzenieKV = inputNapryzenieKV.getCaptionLabel();
labelinputNapryzenieKV.setFont(font);
labelinputNapryzenieKV.setColor(color(#00ffff));
labelinputNapryzenieKV.toUpperCase(false);
labelinputNapryzenieKV.setText("Напряжение");
labelinputNapryzenieKV.align(ControlP5.LEFT_OUTSIDE, CENTER);
labelinputNapryzenieKV.getStyle().setPaddingLeft(-45);
textFont(fontn);
{
// button dimensions
int w = 99;
int h = 25;
// test with generated images
button = new ImageButton(555, 230, w, h,
new PImage[]{
loadImage("0.png"), // off
loadImage("1.png"), // 10
loadImage("2.png"), // 20
loadImage("3.png"), // 30
loadImage("4.png"), // 40
loadImage("5.png"), // 50
loadImage("6.png"), // 60
});
}
}
void mousePressed() {
button.mousePressed(mouseX, mouseY);
println(button.min);
}
// test images to represent loaded state images
PImage getImage(int w, int h, int c) {
PImage img = createImage(w, h, RGB);
java.util.Arrays.fill(img.pixels, c);
img.updatePixels();
return img;
}
// make a custom image button class
class ImageButton {
// minutes is the data it stores
int min = 0;
// images for each state
PImage[] stateImages;
// which image to display
int stateIndex;
// position
int x, y;
// dimensions: width , height
int w, h;
// text to display
String label = "ВЫКЛ";
ImageButton(int x, int y, int w, int h, PImage[] stateImages) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.stateImages = stateImages;
}
void mousePressed(int mx, int my) {
// check the cursor is within the button bounds
boolean isOver = ((mx >= x && mx <= x + w) && // check horizontal
(my >= y && my <= y + h) ); // check vertical
if (isOver) {
min += 10;
stateIndex++;
if (min>60) {
min = 0;
stateIndex = 0;
label = "ВЫКЛ";
} else {
label = (str(min) + "Мин");
}
}
}
void draw() {
// if the images and index are valid
if (stateImages != null && stateIndex < stateImages.length) {
image(stateImages[stateIndex], x, y, w, h);
} else {
println("error displaying button state image");
println("stateImages: ");
printArray(stateImages);
println("stateIndex: " + stateIndex);
}
// display text
//text(label, x + 17, y + h - 8);
}
}
void controlEvent(ControlEvent theEvent) {
if (theEvent.isFrom(CheckBoxuvum)) {
//myColorBackground = 0;
print("got an event from "+CheckBoxuvum.getName()+"\t\n");
// checkbox uses arrayValue to store the state of
// individual checkbox-items. usage:
println(CheckBoxuvum.getArrayValue());
int col = 0;
for (int i=0; i<CheckBoxuvum.getArrayValue().length; i++) {
int n = (int)CheckBoxuvum.getArrayValue()[i];
print(n);
if (n==1) {
//myColorBackground += CheckBoxuvum.getItem(i).internalValue();
}
}
println();
}
if (theEvent.isGroup()) {
// check if the Event was triggered from a ControlGroup
println("event from group : "+theEvent.getGroup().getValue()+" from "+theEvent.getGroup());
} else if (theEvent.isController()) {
println("event from controller : "+theEvent.getController().getValue()+" from "+theEvent.getController());
}
}
Protocol:
int lengthmas = 7;
int RC = 0x21; // -128 separating byte в java
int[] writeOutgioing = new int[lengthmas];
String incomingData= null;
String outgoingData=null;
String[] testRead = new String[lengthmas];
int x;
void readInc() {
while ( serialPort.available() > 0)
{
incomingData = serialPort.readStringUntil(RC);
testRead = split (incomingData, ',' );
if (testRead != null)
{
x = (int) testRead[0].charAt(0);
Displaydata();
}
}
}
void writeOut() {
outgoingData=str(writeOutgioing[0])+str(writeOutgioing[1])+str(writeOutgioing[2])+str(writeOutgioing[3])+str(writeOutgioing[4])+str(writeOutgioing[5])+str(writeOutgioing[6]); // sending data as a string.
serialPort.write(outgoingData);
}
Senddata:
public void toapply()
{
}
loop:
void draw()
{
background(50);
button.draw();
if (strata)
{
readInc();
}
}
code:
inputPULI = cp5.addNumberbox("PUL")
.setLabel("Bullet")
.setPosition(220, 220)
.setSize(80, 30)
.setColorValue(0xffffff00)
.setFont(p)
.setScrollSensitivity(1.1)
.setDirection(Controller.HORIZONTAL)
.setRange(1, 199)
.setValue(3);
Label labelinputPULI = inputPULI.getCaptionLabel();
labelinputPULI.setFont(font);
labelinputPULI.setColor(color(#00ffff));
labelinputPULI.toUpperCase(false);
labelinputPULI.setText("Bullet");
labelinputPULI.align(ControlP5.LEFT_OUTSIDE, CENTER);
labelinputPULI.getStyle().setPaddingLeft(-25);
I figured it out myself, I had to write setLabel->setValueLabel
example
What I've tried.
Please help me.. I really don't know.
I think it's related to canvas class.
CustomLineChartRenderer
It seems to me that color is not filled according to x value, but color is filled at once.
It's hard because I'm not used to canvas. Please help me.
Here are three methods for drawing lines and filling in colors.
#Override
protected void drawLinearFill(Canvas c, ILineDataSet dataSet, Transformer trans, XBounds bounds) {
final Path filled = mGenerateFilledPathBuffer;
final int startingIndex = bounds.min;
final int endingIndex = bounds.range + bounds.min;
final int indexInterval = 128;
int currentStartIndex = 0;
int currentEndIndex = indexInterval;
int iterations = 0;
// Doing this iteratively in order to avoid OutOfMemory errors that can happen on large bounds sets.
do {
currentStartIndex = startingIndex + (iterations * indexInterval);
currentEndIndex = currentStartIndex + indexInterval;
currentEndIndex = currentEndIndex > endingIndex ? endingIndex : currentEndIndex;
if (currentStartIndex <= currentEndIndex) {
generateFilledPath(dataSet, currentStartIndex, currentEndIndex, filled);
trans.pathValueToPixel(filled);
final Drawable drawable = dataSet.getFillDrawable();
if (drawable != null) {
drawFilledPath(c, filled, drawable);
} else {
//////Here part of applying color
drawFilledPath(c, filled, dataSet.getFillColor(), dataSet.getFillAlpha());
}
}
iterations++;
} while (currentStartIndex <= currentEndIndex);
}
#Override
protected void drawFilledPath(Canvas c, Path filledPath, int fillColor, int fillAlpha) {
int color = (fillAlpha << 24) | (fillColor & 0xffffff);
if (clipPathSupported()) {
Log.e("clipPathSupported","1");
int save = c.save();
c.clipPath(filledPath);
c.drawColor(color);
c.restoreToCount(save);
} else {
Log.e("clipPathSupported","2");
// save
Paint.Style previous = mRenderPaint.getStyle();
int previousColor = mRenderPaint.getColor();
// set
mRenderPaint.setStyle(Paint.Style.FILL);
mRenderPaint.setColor(color);
c.drawPath(filledPath, mRenderPaint);
// restore
mRenderPaint.setColor(previousColor);
mRenderPaint.setStyle(previous);
}
}
private void generateFilledPath(final ILineDataSet dataSet, final int startIndex, final int endIndex, final Path outputPath) {
final float fillMin = dataSet.getFillFormatter().getFillLinePosition(dataSet, mChart);
final float phaseY = mAnimator.getPhaseY();
final boolean isDrawSteppedEnabled = dataSet.getMode() == LineDataSet.Mode.STEPPED;
final Path filled = outputPath;
filled.reset();
final Entry entry = dataSet.getEntryForIndex(startIndex);
filled.moveTo(entry.getX(), fillMin);
filled.lineTo(entry.getX(), entry.getY() * phaseY);
// create a new path
Entry currentEntry = null;
Entry previousEntry = entry;
for (int x = startIndex + 1; x <= endIndex; x++) {
currentEntry = dataSet.getEntryForIndex(x);
if (isDrawSteppedEnabled) {
filled.lineTo(currentEntry.getX(), previousEntry.getY() * phaseY);
}
filled.lineTo(currentEntry.getX(), currentEntry.getY() * phaseY);
previousEntry = currentEntry;
}
// close up
if (currentEntry != null) {
filled.lineTo(currentEntry.getX(), fillMin);
}
filled.close();
}
You can use shader, same :
mRenderPaint.shader = LinearGradient(fromX, fromY, toX, toY, color1,
color2,
Shader.TileMode.CLAMP)
I want to implement Levenberg Marquardt fitting in JAVA and found apache commons math suitable. Since I want to fit a function, where I dont have the derivative to calculate the gradient or Jacobian, I need somthing like dfdp.m from GNU octave to calculate numerical derivatives. Has someone done this already?
I did it myself, in case someone else needs it here is the approach
dfdp.m code
m=size(x,1); if (m==1), m=size(x,2); end %# PAK: in case #cols > #rows
n=length(p); %dimensions
ps=p; prt=zeros(m,n);del=zeros(n,1); % initialise Jacobian to Zero
for j=1:n
del(j)=dp(j) .*p(j); %cal delx=fract(dp)*param value(p)
if p(j)==0
del(j)=dp(j); %if param=0 delx=fraction
end
p(j)=ps(j) + del(j);
if del(j)~=0, f1=feval(func,x,p); %FJ ~= not equal (!=) ...> p is now (p + dp*p)
if dp(j) < 0, prt(:,j)=(f1-f)./del(j);
else
p(j)=ps(j) - del(j); %FJ ...> p is now (p - dp*p)
prt(:,j)=(f1-feval(func,x,p))./(2 .*del(j)); %FJ 2 steps from (ps + del) to (ps - del)
end
end
p(j)=ps(j); %restore p(j)
end
JAVA code
private static class GhoosProblem {
private double[][] data;
private double[] dp;
public GhoosProblem(double[][] datapoints, double[] delta_p) {
data = datapoints;
//dp= fractional increment of p for numerical derivatives
//dp(j)>0 central differences calculated
//dp(j)<0 one sided differences calculated
//dp(j)=0 sets corresponding partials to zero; i.e. holds p(j) fixed
dp = delta_p;
}
public MultivariateVectorFunction getModelFunction() {
return new MultivariateVectorFunction() {
public double[] value(double[] params) {
double[] values = new double[data.length];
for (int i = 0; i < values.length; ++i) {
final double t = data[i][0]; // get the double value
values[i] = params[0] *
Math.pow(t, params[2]) *
Math.exp(-params[1] * t); // Ghoos function
}
return values; // function values
}
};
}
public MultivariateMatrixFunction getModelFunctionJacobian2() {
return new MultivariateMatrixFunction() {
public double[][] value(double[] params) {
double[][] jacobian = new double[data.length][params.length];
final double a = params[0];
final double b = params[2];
final double c = params[1];
for (int i = 0; i < jacobian.length; ++i) {
final double t = data[i][0]; // get the double value
jacobian[i][0] = Math.pow(t, b) * Math.exp(-c*t);
jacobian[i][2] = a * Math.exp(-c*t) * Math.pow(t, b) * Math.log(t);
jacobian[i][1] = a * Math.pow(t, b) * (-t*Math.exp(-c*t));
}
//System.out.println("Jacobian= "+ Arrays.deepToString(jacobian));
return jacobian;
}
};
}
// compared to Ge2.m octave
public MultivariateMatrixFunction getModelFunctionJacobian() {
return new MultivariateMatrixFunction() {
public double[][] value(double[] params) {
int m = data.length; // cols
int n = params.length; // rows
double[] p = params;
double[] ps = params;
double[] del = new double[n];
double[] f = new double[n];
double[] f1 = new double[n];
BlockRealMatrix prt = new BlockRealMatrix(m, n); // initializes to zeros
f=feval(p);
for (int j=0; j<n; ++j) {
del[j]=dp[j] * p[j]; //delta_x=fractional(dp) * param value(p)
if (p[j]==0)
del[j]=dp[j]; //if param=0 delta_x=fractional(dp)
p[j]=ps[j] + del[j];
if (del[j]!=0) {
f1=feval(p); //p is now (p + dp*p)
if (dp[j]<0)
prt.setColumn(j,(new ArrayRealVector(f1)).subtract(new ArrayRealVector(f)).mapDivideToSelf(del[j]).toArray()); // one sided diff
else {
p[j]=ps[j] - del[j]; // p is now (p - dp*p)
prt.setColumn(j,(new ArrayRealVector(f1)).subtract(new ArrayRealVector(feval(p))).mapDivideToSelf(2*del[j]).toArray()); // central diff
}
}
p[j]=ps[j]; //restore p(j)
}//for
//System.out.println("Jacobian= "+ Arrays.deepToString(prt.getData()));
return prt.getData(); //jacobian, dimension is (m x n)
}
};
}
public double[] feval(double[] params) {
double[] values = new double[data.length];
for (int i = 0; i < values.length; ++i) {
final double t = data[i][0]; // get the double value
values[i] = params[0] *
Math.pow(t, params[2]) *
Math.exp(-params[1] * t); // Ghoos function
}
return values;
}
}//GhoosProblem
sorry if idention of code did not come out nice!
the relevant part is the getModelFunctionJacobian() -Function
I have renamed the analytical derivatives part as getModelFunctionJacobian2(), and posted here for comparison
to complete with here is the levenberg marquardt setup to use the GhoosFunction
public void fit() {
final double[][] dataPoints = { // x, y
//{0.0/60, 0.0}, // never use {0, 0} => org.apache.commons.math3.exception.ConvergenceException: illegal state: unable to perform Q.R decomposition on the 17x3 jacobian matrix
{15.0/60, 8.891104},
{30.0/60, 13.21852},
{45.0/60, 28.09051},
{60.0/60, 43.0011},
{75.0/60, 57.43561},
{90.0/60, 67.06862},
{105.0/60, 82.60239},
{120.0/60, 72.4649},
{135.0/60, 61.4},
{150.0/60, 43.97924},
{165.0/60, 30.6},
{180.0/60, 20.77112},
{195.0/60, 15.5},
{210.0/60, 10.85442},
{225.0/60, 9.33},
{240.0/60, 7.260234},
};
final double[] initialGuess = { 1.0, 1.0, 1.0 }; // p
final double[] fract_change = { 1E-4, 1E-4, 1E-4 }; // dp should be below 0.0001
final GhoosProblem problem = new GhoosProblem(dataPoints, fract_change);
final int len = dataPoints.length;
final double[] weights = new double[len];
final double[] target = new double[len];
for (int i = 0; i < len; i++){
weights[i] = 1.0;// / dataPoints[i][1];
target[i] = dataPoints[i][1];
}
final LevenbergMarquardtOptimizer optimizer = new LevenbergMarquardtOptimizer()
.withCostRelativeTolerance(1E-4) // stol in octave
.withParameterRelativeTolerance(1E-4); // dp should be below 0.0001
final Optimum optimum = optimizer.optimize(
builder(problem)
.weight(new DiagonalMatrix(weights))
.target(target)
.start(initialGuess)
.maxIterations(100)
.build()
);
final RealVector solution = optimum.getPoint();
solution.setEntry(0, solution.getEntry(0) / 60.0); // go back to minutes
System.out.println("solution= " + solution);
System.out.println("CostRelativeTolerance= " + optimizer.getCostRelativeTolerance());
System.out.println("ParameterRelativeTolerance= " + optimizer.getParameterRelativeTolerance());
System.out.println("evaluations= " + optimum.getEvaluations());
System.out.println("iterations= " + optimum.getIterations());
//System.out.println("residuals= " + optimum.getResiduals());
System.out.println("RMS= " + optimum.getRMS());
System.out.println("sigma= " + optimum.getSigma(1E-10));
}//fit
public LeastSquaresBuilder builder(GhoosProblem problem){
return new LeastSquaresBuilder()
.checkerPair(new SimpleVectorValueChecker(1e-6, 1e-6)) // The SimpleVectorValueChecker Class (Simple implementation of the ConvergenceChecker) contains a method that uses the value of the function between two successive iterations of the optimisation algorithm to check if convergence has occured
.maxEvaluations(Integer.MAX_VALUE)
.maxIterations(Integer.MAX_VALUE)
//.lazyEvaluation(true)
.model(problem.getModelFunction(), problem.getModelFunctionJacobian());
}
I have a 90 frames animation and i want to display it on the minecraft hud.
Here is the code i use now:
String CType = "Target";
int CSpeed = 30;
int fast = 0;
public int CenterRoteryCounter = 0;
#ForgeSubscribe
public void CenterRotery(RenderGameOverlayEvent.Post event){
//========Resolution========
res = new ScaledResolution(mc.gameSettings, mc.displayWidth, mc.displayHeight);
int width = res.getScaledWidth();
int height = res.getScaledHeight();
//========Resolution========+
if(CenterRoteryCounter == 90){CenterRoteryCounter = 0;}
if(CenterRoteryCounter < 10){
this.mc.renderEngine.func_110577_a(new ResourceLocation("CenterRotery/"+CType+"000" + CenterRoteryCounter + ".png"));
}else{if(CenterRoteryCounter < 100){
this.mc.renderEngine.func_110577_a(new ResourceLocation("CenterRotery/"+CType+"00" + CenterRoteryCounter + ".png"));
}else{
this.mc.renderEngine.func_110577_a(new ResourceLocation("CenterRotery/"+CType+"0" + CenterRoteryCounter + ".png"));
}
}
drawTexturedModalRect((width/2)-44, (height/2)-37, 0, 0, 250, 250);
mc.func_110434_K().func_110577_a(Gui.field_110324_m);
if((fast % CSpeed)==0){CenterRoteryCounter++;}fast++;
}
but as you can see, this is creating ~30 new ResourceLocations every second..!!
How can i pre-load the textures and display them the same way?
You can simply use a private static final Hashmap from your class in a method getResourceLocation(String resourceLocation). Something like :
private static ResourceLocation getResourceLocation(String resourceLocation) {
ResourceLocation myRes = myHashMap.get(resourceLocation);
if (myRes == null) {
myRes = new ResourceLocation(resourceLocation);
myHashMap.put(resourceLocation, myRes);
}
return myRes;
}
It will cache your resources on demand. Just be sure of the necessary amount of memory needed !