I am using the MPAndroidChart library. I need to create a straight line of ~ 500 points. The problem is that I do not see the graph itself and the points. But if I manually add 5 points and build a graph on them, then everything will be displayed correctly.
I suspect that it is necessary to somehow solve the problem of displaying a large number of points, since they overlap each other.
ArrayList<Entry> values = new ArrayList<>();
//default: x1 = 200; x2 = 700
for (int i = x1, index = 0, j = y; i < x2; ++i, ++index)
{
float waveLength = (float) calib_a * i + (float) calib_b;
int pixel = rotated.getPixel(i, j);
float I = (Color.red(pixel) + Color.blue(pixel) + Color.green(pixel)) / 765.0f;
values.add(new Entry(waveLength, I));
Log.d("[SPECTRAl]", " WAVE: " +waveLength + " I: " + I);
}
LineDataSet lineValues = new LineDataSet(values, "");
LineData line = new LineData(lineValues);
chart.setData(line);
chart.invalidate();
xml:
<com.github.mikephil.charting.charts.LineChart
android:id="#+id/chart"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Related
I am trying to detect and crop circullar/elliptical shapes of different sizes.
This is an example of an image I am trying to do the detection and croping.
Input Image
The result I am trying to get in the aforementioned image is 3 cropped images
looking like this:
segmented part 1, segmented part 2, segmented part 3
Another image could look like this: different image
Just like the previous image, I am trying to do the same to this one.
The shapes are dramatically smaller from the first one.
Can this be achieved algorithmically or should I look for a machine learning-like solution?
Note: The final image has been applied by the following filters: Gaussian Blur, Grayscale, Threshold, Contour and Morphological Dilation.
[EDIT]
The code I have written(not working as intended):
findReference() finds a shape in the middle of the image and returns its rectangle.
private Rect findReference(Mat inputImage) {
// clone the image
Mat original = inputImage.clone();
// find the center of the image
double[] centers = {(double)inputImage.width()/2, (double)inputImage.height()/2};
Point image_center = new Point(centers);
// finding the contours
ArrayList<MatOfPoint> contours = new ArrayList<MatOfPoint>();
Mat hierarchy = new Mat();
Imgproc.findContours(inputImage, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
// finding best bounding rectangle for a contour whose distance is closer to the image center that other ones
double d_min = Double.MAX_VALUE;
Rect rect_min = new Rect();
for (MatOfPoint contour : contours) {
Rect rec = Imgproc.boundingRect(contour);
// find the best candidates
if (rec.height > inputImage.height()/2 & rec.width > inputImage.width()/2){
continue;
}
Point pt1 = new Point((double)rec.x, (double)rec.y);
Point center = new Point(rec.x+(double)(rec.width)/2, rec.y + (double)(rec.height)/2);
double d = Math.sqrt(Math.pow((double)(pt1.x-image_center.x),2) + Math.pow((double)(pt1.y -image_center.y), 2));
if (d < d_min)
{
d_min = d;
rect_min = rec;
}
}
// showReference( rect_min, original);
return rect_min;
}
I use the rectangle as reference and create a bigger one and a smaller one, so that similar shapes fit in the dimensions of the smaller and bigger rectangle.
findAllEllipses() tries to find similar shapes fitting in the smaller and bigger rectangles. After that it draws ellipses around the found shapes.
private Mat findAllEllipses(Rect referenceRect, Mat inputImage) {
float per = 0.5f;
float perSquare = 0.05f;
Rect biggerRect = new Rect();
Rect smallerRect = new Rect();
biggerRect.width = (int) (referenceRect.width / per);
biggerRect.height = (int) (referenceRect.height / per);
smallerRect.width = (int) (referenceRect.width * per);
smallerRect.height = (int) (referenceRect.height * per);
System.out.println("reference rectangle height: " + referenceRect.height + " width: " + referenceRect.width);
System.out.println("[" + 0 +"]: biggerRect.height: " + biggerRect.height + " biggerRect.width: " + biggerRect.width);
System.out.println("[" + 0 +"]: smallerRect.height: " + smallerRect.height + " smallerRect.width: " + smallerRect.width);
//Finding Contours
List<MatOfPoint> contours = new ArrayList<>();
Mat hierarchey = new Mat();
Imgproc.findContours(inputImage, contours, hierarchey, Imgproc.RETR_TREE,
Imgproc.CHAIN_APPROX_SIMPLE);
System.out.println("the numbers of found contours is: " + contours.size());
int sum = 0;
//Empty rectangle
RotatedRect[] rec = new RotatedRect[contours.size()];
for (int i = 0; i < contours.size(); i++) {
rec[i] = new RotatedRect();
if(contours.get(i).toArray().length >= 5 ){
Rect foundRect = Imgproc.boundingRect(contours.get(i));
// Rect foundBigger = new Rect();
// Rect foundSmaller = new Rect();
//
// foundBigger.width = (int) (foundBigger.width + foundBigger.width * per);
// foundBigger.height = (int) (foundBigger.height + foundBigger.height * per);
//
// foundSmaller.width = (int) (foundRect.width - foundRect.width * per);
// foundSmaller.height = (int) (foundRect.height - foundRect.height * per);
if (
(biggerRect.height >= foundRect.height && biggerRect.width >= foundRect.width)
&& (smallerRect.height <= foundRect.height && smallerRect.width <= foundRect.width)
&& (((foundRect.width - foundRect.width * perSquare) <= foundRect.height) && ((foundRect.width + foundRect.width * perSquare) >= foundRect.height))
&& (((foundRect.height - foundRect.height * perSquare) <= foundRect.width) && ((foundRect.height + foundRect.height * perSquare) >= foundRect.width))
) {
System.out.println("[" + i +"]: foundRect.width: " + foundRect.width + " foundRect.height: " + foundRect.height);
System.out.println("----------------");
rec[i] = Imgproc.fitEllipse(new MatOfPoint2f(contours.get(i).toArray()));
sum++;
}
}
Scalar color_elli = new Scalar(190, 0, 0);
Imgproc.ellipse(inputImage, rec[i], color_elli, 5);
}
System.out.println("found ellipses: " + sum);
// trytest(ImageUtils.doResizeMat(outputImage),0,0);
return inputImage;
}
Unfortuantelly there are several variables that are hardcoded into the method.
This is used to make the smaller and bigger rectangles (used as a percentage)
float per = 0.5f;
perSquare is used to get shapes closer to a square (fluctuated width height)
float perSquare = 0.05f;
This code might work in some images, while on others will not find a single shape, like I mentioned the shapes are circullar/elliptical and of different sizes.
I am creating small firework simulation in LibGDX. I have ArrayList called particles and this is filling it:
for (int i = 0; i < 2; i++) {
Particle p = new Particle();
p.position = position;
p.velocity.x = MathUtils.random(-1f, 1f);
p.velocity.y = MathUtils.random(-1f, 1f);
particles.add(p);
}
And then in update loop:
for (int i = 0; i < particles.size(); i++) {
System.out.println(i + " " + particles.get(i).position.toString() + " + " + particles.get(i).velocity.toString() + " = ");
particles.get(i).update();
System.out.println(" " + particles.get(i).position.toString());
}
Particle update function:
velocity.add(acceleration);
position.add(velocity);
acceleration.set(0, 0);
Velocity is random and every particle have unique velocity but position is the same. Here is output:
0 (300.0,620.91364) + (-0.94489133,-0.45628428) =
(299.0551,620.45734)
1 (299.0551,620.45734) + (0.3956585,0.5208683) =
(299.45078,620.9782)
0 (299.45078,620.9782) + (-0.94489133,-0.45628428) =
(298.5059,620.5219)
1 (298.5059,620.5219) + (0.3956585,0.5208683) =
(298.90155,621.0428)
0 (298.90155,621.0428) + (-0.94489133,-0.45628428) =
(297.95667,620.5865)
1 (297.95667,620.5865) + (0.3956585,0.5208683) =
(298.35233,621.10736)
First is particle index, position, velocity and then output position.
Why is it using position from another particle? I am trying to figure it out but I can't.
In your for loop where you fill the ArrayList you have the line:
p.position = position;
I don't know where position comes from but here all Particles point to the same.
You must create a new Position for every Particle
p.position = new Position(x, y);
If position is the start point for your Particles you can write:
p.position = new Position(position.x, position.y);
I'm not really sure how to even describe this problem so please excuse the terrible title. I have a simple model ( it is actually a tile but I made it a cube to better illustrate the issue ) that is 2 units high, wide and deep. To draw a continuous field of these I simply increment X and Z by 2 appropriately and they all render nicely next to one another. If I want to create a step up so my flat field has a new level to it I add 2 to the Y value for a segment of the field expecting that the bottom of the top level would then align perfectly with the top of the lower level.
What actually happens is the top level renders a fair distance above the lower level. Why? What would cause this? I ran some tests and found that I'd have to increment Y by a number somewhere between 0.6 and 0.7 for the bottom to align properly with the top.
I thought maybe it was the viewport but I think that is fine. The models don't look warped. Has anyone run into something like this before?
See the attached image for an example of what I'm talking about. The red line illustrates this strange separation of the top and bottom layers.
The Render function
public void draw() throws Exception {
float x = 0;
double y = 0;
float z = 0;
int cidx = 0;
boolean firstCube = true;
glfwSwapBuffers(window); // swap the color buffers
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the framebuffer
//calc rotate camera
if (updatecamera == true){
updateCamera();
}
glUseProgram(shader.iProgram);
//some lighting...
Vector4f lp = new Vector4f(lightX, lightY, lightZ,1.0f);
//float[] lp = {xa, ya + 100, za - 120,1.0f}; //set light source to same as camera eye for now.
shader.setUniform(iLightCam, camera);
shader.setUniform(iLightVec, lp);
//get picking ray
if (worldClicked == true){
pick = makeRay(pick, cursorX, (DISPLAY_HEIGHT - ((DISPLAY_HEIGHT - VP_HEIGHT) / 2)) - cursorY);
}
for(Iterator<Quad> qd = quads.iterator(); qd.hasNext(); ) {
//init cull check
frust.cullIn = 0;
frust.cullOut = 0;
quad = qd.next();
pickthisQuad = false;
firstCube = true; //the first cube is used to set the values of the Quad OBB.
for(Iterator<Cube> i = quad.cubes.iterator(); i.hasNext(); ) {
cb = i.next();
x = cb.x;
z = cb.z;
//y = cb.y;
//testing odd Y behaviour
if ( y == 0) {
y = lightX;
}else{
y = 0;
}
System.out.println(" y: " + y);
//init
model.setIdentity();
//ROTATE
//set translate
vTrans.set(transx + x, (float) (transy + y), transz + z);
Matrix4f.translate(vTrans, model1, model);
vTrans.set(-(transx + x), (float) (-transy + y), -(transz + z));
Matrix4f.translate(vTrans, model, model);
Matrix4f.rotate((float) Math.toRadians(rotY), new Vector3f(0,1,0), model, model);
vTrans.set((transx + x), (float) (transy + y), (transz + z));
Matrix4f.translate(vTrans, model, model);
Matrix4f.mul(model, camera, modelview);
shader.setUniform(iModelView, modelview);
Matrix3f norm = new Matrix3f();
norm.m00 = modelview.m00;
norm.m01 = modelview.m01;
norm.m02 = modelview.m02;
norm.m10 = modelview.m10;
norm.m11 = modelview.m11;
norm.m12 = modelview.m12;
norm.m20 = modelview.m20;
norm.m21 = modelview.m21;
norm.m22 = modelview.m22;
shader.setUniform(iNorm, norm);
shader.setUniform(iProj, projection);
shader.setUniform(iCam, camera);
shader.setUniform(iModel, model);
test_renderFrustumandCrosslines();
manageTextures(cb);
render();
cidx++;
}//cubes
cidx = 0;
}//quads
/**
* TESTING
*/
glUseProgram(shaderLine.iProgram);
Matrix4f mvp = new Matrix4f();
mvp.setIdentity();
Matrix4f.mul(projection, camera, mvp);
shaderLine.setUniform(iMVPLine, mvp);
renderLine();
renderCross();
worldClicked = false;
glFinish();
}
Is there any special thoughts about the 2 first translates in the rotation code? The x ans z translations will cancel each other out but not the y axis. Which could be the source of the problem.
vTrans.set(transx + x, (float) (transy + y), transz + z);
Matrix4f.translate(vTrans, model1, model);
vTrans.set(-(transx + x), (float) (-transy + y), -(transz + z));
Matrix4f.translate(vTrans, model, model);
What happens if you remove these 4 lines? You still do the translation after the rotation.
I have a list of vertices and a list of regions (which are square/rectangle) shaped. Vertex has x and y coordinates, and a region has (x, y, height and width). How can I efficiently check which vertex lies in which region for every vertex/region?
EDIT:
This is the code I wrote to do this.
if (!g.getVertices().isEmpty()) {
for (int i = 0; i < g.getVertices().size(); i++) {
Vertex v = g.getVertices().get(i);
Point vertexPoint = new Point(v.getX(), v.getY());
for (int j = 0; j < g.getNumberOfRegions(); j++) {
int x = g.getRegions().get(j).getX();
int y = g.getRegions().get(j).getY();
int height = g.getRegions().get(j).getHeight();
int width = g.getRegions().get(j).getWidth();
Grid regionGrid = new Grid(j+1, x, y, height, width);
Rectangle regionRectangle = new Rectangle(x, y, height, width);
if (regionRectangle.contains(vertexPoint)) {
System.out.println("Vertex " + v + " lies inside region " + regionGrid.getRegionID());
}
}
}
}
EDIT 2: I used this to generate the regions, but I need a way to assign each region in the grid a regionID from left to right. For example:
1 - 2 - 3
4 - 5 - 6
7 - 8 - 9
for a 3x3 grid. At the moment it is in the following form:
1 - 1 - 1
2 - 2 - 2
3 - 3 - 3
for (int i = 0; i < rowValue; i++) {
for (int j = 0; j < columnValue; j++) {
Grid r = new Grid(0, 20 + i * size, 20 + j * size, size, size);
r.setRegionID(j + 1);
g.addRegion(r);
}
}
checking if a vertex is inside a square or a circle can be done in O(1). you can do it with library function or elementary math. so the works algorithm you can create is O(#vertices * #regions). you can try to optimise by sorting the vertices and regions by X-axis and then by Y-axis and try to eliminate checking that for sure return false. but seems that in pessimistic scenario you will still have O(#vertices * #regions) time.
You can probably use the Core Java libraries itself:
List<Rectangle2D.Double> rectangles = Arrays.asList(
new Rectangle2D.Double(0d, 0d, 100d, 100d),
new Rectangle2D.Double(100d, 0d, 100d, 100d),
new Rectangle2D.Double(0d, 100d, 100d, 100d),
new Rectangle2D.Double(100d, 100d, 100d, 100d));
Point2D.Double aPoint = new Point2D.Double(30d, 40d);
for (Rectangle2D.Double rectangle:rectangles){
if (rectangle.contains(aPoint)){
System.out.println(rectangle + " has the point " + aPoint);
}
}
Working with plane geometry is extremely easy while using JTS. You can try convert the objects you are using to JTS-specific.
I have a chart in excel that represents some value over a one day period. So I add the reference function and I get something like this:
y = 1E-13x6 - 2E-10x5 + 8E-08x4 - 1E-05x3 + 0,0004x2 + 0,0275x + 8,414
A mesure in my data set is:
09:36:21 => 5,27
The firts thing I need to know is how to transform the timestamp into a value to give to the function. After some cell value transforming I've found out that excel gives timestamps a representation between 0.00000 and 0.99999, so for example 09:36:21 is 0.400243055555556. Then I've coded a little java test script:
double x = 0.400243055555556;
double x6 = (1*Math.pow(10, -13))*Math.pow(x, 6);
double x5 = (2*Math.pow(10, -10))*Math.pow(x, 5);
double x4 = (8*Math.pow(10, -8))*Math.pow(x, 4);
double x3 = (1*Math.pow(10, -5))*Math.pow(x, 3);
double x2 = (4*Math.pow(10, -4))*Math.pow(x, 2);
double y = x6 - x5 + x4 - x3 + x2 + 0.0275*x + 8.414;
But after executing this script I get y = 8.425070122712738. So this is obviously not working. I must say that all the values in the chart range from 5 to 12.
I'm obviously doing something wrong, but I don't know what. Maybe I've coded the function badly, or maybe the x I'm choosing is not a right value, but something is wrong. Can anyone help?
Update: My code wasn't that good, what duffymo suggested worked better. But the problem was that Excel was giving my the wrong tendendy line. I've managed to get the good one using a scatter graph.
I would not recommend coding it this way - roundoff could be an issue.
I would recommend Horner scheme:
I coded it this way and got the same answer that you did:
public class Horner
{
public static final NumberFormat DEFAULT_FORMAT = new DecimalFormat("0.000");
public static void main(String[] args)
{
double [] a = { 8.414, 0.0275, 0.0004, -1.0e-5, 8.0e-8, -2.0e-10, 1.0e-13 };
for (double x = 0.0; x < 1.0; x += 0.05)
{
double y = a[0] + x*(a[1] + x*(a[2] + x*(a[3] + x*(a[4] + x*(a[5])))));
System.out.println("x = " + DEFAULT_FORMAT.format(x) + " y = " + DEFAULT_FORMAT.format(y));
}
}
}
Here's the result I get. The higher order terms aren't doing much good; the coefficients are small, and when you raise a fraction to a power it diminishes the effect even more.
x = 0.000 y = 8.414
x = 0.050 y = 8.415
x = 0.100 y = 8.417
x = 0.150 y = 8.418
x = 0.200 y = 8.420
x = 0.250 y = 8.421
x = 0.300 y = 8.422
x = 0.350 y = 8.424
x = 0.400 y = 8.425
x = 0.450 y = 8.426
x = 0.500 y = 8.428
x = 0.550 y = 8.429
x = 0.600 y = 8.431
x = 0.650 y = 8.432
x = 0.700 y = 8.433
x = 0.750 y = 8.435
x = 0.800 y = 8.436
x = 0.850 y = 8.438
x = 0.900 y = 8.439
x = 0.950 y = 8.440
Still not what you want, but I think the coding is far simpler.