I want to print numbers from 0 to 100 clockwise on canvas it will work when we have values from 0 to 12 but once i changed the values or increased the it is stopped working in my case can anyone help me here?
private int[] mClockHours = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12};
private void drawNumeral(Canvas canvas) {
mPaint.setTextSize(fontSize);
for (int number : mClockHours) {
String tmp = String.valueOf(number);
mPaint.getTextBounds(tmp, 0, tmp.length(), mRect);
double angle = Math.PI / 6 * (number - 2);
Log.d("drawNumeral", "number: "+number);
Log.d("drawNumeral", "Math.PI: "+Math.PI);
Log.d("drawNumeral", "angle: "+angle);
Log.d("drawNumeral", "temp: "+tmp);
int x = (int) (width / 2 + Math.cos(angle) * mRadius - mRect.width() / 2);
int y = (int) (height / 2 + Math.sin(angle) * mRadius - mRect.height() / 2);
canvas.drawText(tmp, x, y, mPaint);
}
}
You need to invalidate() the view to see changes you made. Here is a good tutorial to understand how to draw on canvas.
Related
First thing I have drawn the three lines of the hexagon width specific width then I have drawn the six points using this formula section = 2 * PI / NumberOfPoints. Here is the pic of lines I have drawn:
what I want is to draw a triangle between every two lines which will be 6 triangles. Here is the pic when I drew the triangles:
My problem is I want the triangle to be drawn between the lines, not above them which mean the triangle should not overlaps the line.
Here is how I drew the lines:
for (int i = 1; i <= 6; i++) {
float eX = (float) (x + radius * Math.cos(section * i));
float eY = (float) (y + radius * Math.sin(section * i));
linesPaint.setShader(new LinearGradient(x, y, eX, eY, Color.BLACK, Color.TRANSPARENT, Shader.TileMode.MIRROR));
canvas.drawLine(x, y, eX, eY, linesPaint);
}
and here is how I drew the triangles
for (int i = 1; i <= 6; i++) {
TriangleColor triangleColor = triangleColors.get(i - 1);
trianglesPaint.setShader(new LinearGradient(0, 0, 0, getHeight(), triangleColor.firstColor, triangleColor.secondColor, Shader.TileMode.REPEAT));
float x1 = (float) (x + radius * Math.cos(section * i));
float y1 = (float) (y + radius * Math.sin(section * i));
float x2 = (float) (x + radius * Math.cos(section * (i + 1)));
float y2 = (float) (y + radius * Math.sin(section * (i + 1)));
trianglesPath.moveTo(x, y);
trianglesPath.lineTo(x1, y1);
trianglesPath.lineTo(x2, y2);
trianglesPath.lineTo(x, y);
canvas.drawPath(trianglesPath, trianglesPaint);
trianglesPath.reset();
}
Can anyone help me with the formula? Thanks in advance.
I assume that you have lines with thickness 2d
To avoid overwriting these lines, you can shift the central point for every triangle by dstance d/sin(30) = 2*d in direction of bisector between two lines
Perhaps also you need to diminish radius (length of triangle side along the line)
newradius = radius - d*sqrt(3) - d * sqrt(3)/3
for (int i = 1; i <= 6; i++) {
cx = x + 2 * d * Math.cos(section * (i + 0.5));
cy = x + 2 * d * Math.sin(section * (i + 0.5));
float x1 = (float) (cx + newradius * Math.cos(section * i)); /
//and similar for other coordinates
trianglesPath.moveTo(cx, cy);
trianglesPath.lineTo(x1, y1);
...
I am trying to create a spray can tool in Android for a Graffiti app. I want to achieve something similar done in the below image
Dripping Spray Can Sample image
Requirements: If somebody is spraying the can then it should drip some color downwards while drawing a spray line
I am currently using the following code, but not getting the correct results:
if (bufferPaint == null) {
bufferPaint = new Paint();
bufferPaint.setAntiAlias(true);
bufferPaint.setDither(true);
bufferPaint.setXfermode(null);
if (mPaint == null)
setupColor(0f, 100f);
}
int alpha = Math.round((float) 100 / 100 * 255);
bufferPaint.setAlpha(alpha);
private void paintOneDab(float x, float y) {
float radius = 5 / 2f;
float scatter = 500 / 100f;
x += radius 2 scatter (1 - 2 (float) Math.random());
y += radius 2 scatter (1 - 2 (float) Math.random());
float hardness = 20 / 100f;
positions[0] = 0;
positions[1] = (float) (Math.sqrt(hardness));
positions[2] = 1;
bufferPaint.setShader(new RadialGradient(x, y, radius, colors, positions, Shader.TileMode.CLAMP));
mCanvas.save();
int angle = 180;
mCanvas.rotate(angle, x, y);
int roundness = 100;
mCanvas.scale(1f, 100f / roundness, x, y);
mCanvas.drawCircle(x, y, radius, bufferPaint);
mCanvas.restore();
}
I'm creating a drawing app, and I want on of the brushes the user can draw with to have the following effect:
Currently, to achieve this effect, I'm drawing 5 separate Paths, each with the same X values but a small Y offset, and each with a BlurMaskFilter. Here's the code from the PaintBrush class:
public PaintBrush(int initColor, int initSize) {
strokeRadius = ((10 * initSize) + 20) / 2;
currentColor = initColor
setupPaths();
}
private void setupPaths(){
paths = new Path[5];
paints = new Paint[5];
for (int i = 0; i < 5; i++){
paths[i] = new Path();
Paint curPaint = new Paint();
curPaint.setColor(currentColor);
curPaint.setAntiAlias(true);
curPaint.setDither(true);
curPaint.setStyle(Paint.Style.STROKE);
curPaint.setStrokeJoin(Paint.Join.ROUND);
curPaint.setStrokeCap(Paint.Cap.ROUND);
paints[i] = curPaint;
}
Paint paint1 = paints[0];
paint1.setStrokeWidth(strokeRadius / 3);
paint1.setMaskFilter(new BlurMaskFilter(Math.max(strokeRadius / 5, 1), BlurMaskFilter.Blur.NORMAL));
Paint paint2 = paints[1];
paint2.setStrokeWidth(strokeRadius / 6);
paint2.setMaskFilter(new BlurMaskFilter(Math.max(strokeRadius / 7, 1), BlurMaskFilter.Blur.NORMAL));
Paint paint3 = paints[2];
paint3.setStrokeWidth(strokeRadius / 5);
paint3.setMaskFilter(new BlurMaskFilter(Math.max(strokeRadius / 7, 1), BlurMaskFilter.Blur.NORMAL));
Paint paint4 = paints[3];
paint4.setStrokeWidth(strokeRadius / 3);
paint4.setMaskFilter(new BlurMaskFilter(Math.max(strokeRadius / 4, 1), BlurMaskFilter.Blur.NORMAL));
Paint paint5 = paints[4];
paint5.setStrokeWidth(strokeRadius / 4);
paint5.setMaskFilter(new BlurMaskFilter(Math.max(strokeRadius / 4, 1), BlurMaskFilter.Blur.NORMAL));
}
public void drawBrush(Canvas canvas){
for (int i = 0; i < 5; i++) {
canvas.drawPath(paths[i], paints[i]);
}
}
public void startStroke(float x, float y){
paths[0].moveTo(x, y - (strokeRadius * 4 / 6));
paths[1].moveTo(x, y - (strokeRadius / 3));
paths[2].moveTo(x, y - (strokeRadius / 8));
paths[3].moveTo(x, y + (strokeRadius / 3));
paths[4].moveTo(x, y + (strokeRadius * 3 / 4));
prevX = x;
prevY = y;
}
public void moveStroke(float x, float y){
float dx = Math.abs(x - prevX);
float dy = Math.abs(y - prevY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
paths[0].quadTo(prevX, prevY - (strokeRadius * 4 / 6), (x + prevX) / 2, ((y + prevY) / 2) - (strokeRadius * 4 / 6));
paths[1].quadTo(prevX, prevY - (strokeRadius / 3), (x + prevX) / 2, ((y + prevY) / 2) - (strokeRadius / 3));
paths[2].quadTo(prevX, prevY - (strokeRadius / 8), (x + prevX) / 2, ((y + prevY) / 2) - (strokeRadius / 8));
paths[3].quadTo(prevX, prevY + (strokeRadius / 3), (x + prevX) / 2, ((y + prevY) / 2) + (strokeRadius / 3));
paths[4].quadTo(prevX, prevY + (strokeRadius * 3 / 4), (x + prevX) / 2, ((y + prevY) / 2) + (strokeRadius * 3 / 4));
}
prevX = x;
prevY = y;
}
public void endStroke(Canvas canvas){
drawBrush(canvas);
paths[0].reset();
paths[1].reset();
paths[2].reset();
paths[3].reset();
paths[4].reset();
}
And the code for the custom View:
#Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(drawingCanvas, 0, 0, canvasPaint);
currentBrush.drawBrush(canvas);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (!activity.isPaused()) {
float touchX = event.getX();
float touchY = event.getY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
currentBrush.startStroke(touchX, touchY);
break;
case MotionEvent.ACTION_MOVE:
currentBrush.moveStroke(touchX, touchY);
break;
case MotionEvent.ACTION_UP:
currentBrush.endStroke(touchX, touchY, drawingCanvas);
break;
default:
return false;
}
invalidate();
}
return true;
}
I'm aware that BlurMaskFilter is not compatible with hardware accelerations, so in my main activity i have the following code:
drawingView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
This code works, however, with hardware acceleration disabled, my drawing activity took a massive (and unacceptable) performance hit; it draws with a extremely noticeable lag, especially as the paths get longer. My question is: is there a way I could increase the performance, without using hardware acceleration, enough to decrease the lag? If not, is there any way to emulate this same effect in ways that are compatible with hardware acceleration?
Keep a Bitmap of the size of the entire screen.
Keep a list of all points that the finger moved through. Have some minimal threshold for the distance from the previous touch point to the last one. You essentially break the drawing motion into a list of points.
Now, every time the finger moves, find the bounding rectangle of the area that was changed since the last touch event you handled, clear this rectangle, and redraw only the lines on the list that are in this rectangle with your drawPath.
You can try using the RasmView library: github.com/Raed-Mughaus/DrawingVie
I am developing an android application where I need to detect the blinking of eyes. So far I have been able to detect the face and eyes using OpenCV. But now I need to check if the eyes are open or close. I read somewhere that one of the ways I can do that is by measuring the pixel intensities (grey levels). But it was not properly explained as in how to do that step by step. I am actually new to OpenCV. So can anyone please help me how can I do that. It is really very important.
Here is my onCameraFrame method:
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
mRgba = inputFrame.rgba();
mGray = inputFrame.gray();
if (mAbsoluteFaceSize == 0) {
int height = mGray.rows();
if (Math.round(height * mRelativeFaceSize) > 0) {
mAbsoluteFaceSize = Math.round(height * mRelativeFaceSize);
}
}
if (mZoomWindow == null || mZoomWindow2 == null)
CreateAuxiliaryMats();
MatOfRect faces = new MatOfRect();
if (mJavaDetector != null)
mJavaDetector.detectMultiScale(mGray, faces, 1.1, 2,
2, // TODO: objdetect.CV_HAAR_SCALE_IMAGE
new Size(mAbsoluteFaceSize, mAbsoluteFaceSize),
new Size());
Rect[] facesArray = faces.toArray();
for (int i = 0; i < facesArray.length; i++) {
Core.rectangle(mRgba, facesArray[i].tl(), facesArray[i].br(),
FACE_RECT_COLOR, 2);
xCenter = (facesArray[i].x + facesArray[i].width + facesArray[i].x) / 2;
yCenter = (facesArray[i].y + facesArray[i].y + facesArray[i].height) / 2;
Point center = new Point(xCenter, yCenter);
Rect r = facesArray[i];
// compute the eye area
Rect eyearea = new Rect(r.x + r.width / 20,
(int) (r.y + (r.height / 20)), r.width - 2 * r.width / 20,
(int) (r.height / 9.0));
// split it
Rect eyearea_right = new Rect(r.x + r.width / 6,
(int) (r.y + (r.height / 4)),
(r.width - 2 * r.width / 16) / 3, (int) (r.height / 4.0));
Rect eyearea_left = new Rect(r.x + r.width / 11
+ (r.width - 2 * r.width / 16) / 2,
(int) (r.y + (r.height / 4)),
(r.width - 2 * r.width / 16) / 3, (int) (r.height / 4.0));
// draw the area - mGray is working grayscale mat, if you want to
// see area in rgb preview, change mGray to mRgba
Core.rectangle(mRgba, eyearea_left.tl(), eyearea_left.br(),
new Scalar(255, 0, 0, 255), 2);
Core.rectangle(mRgba, eyearea_right.tl(), eyearea_right.br(),
new Scalar(255, 0, 0, 255), 2);
if (learn_frames < 5) {
teplateR = get_template(mJavaDetectorEye, eyearea_right, 24);
teplateL = get_template(mJavaDetectorEye, eyearea_left, 24);
learn_frames++;
} else {
// Learning finished, use the new templates for template
// matching
match_eye(eyearea_right, teplateR, method);
match_eye(eyearea_left, teplateL, method);
}
}
return mRgba;
}
Thanks in advance.
I already worked on this problem and this algorithm. It's implemented (C++) here: https://github.com/maz/blinking-angel with algorithm here: http://www.cs.bu.edu/techreports/pdf/2005-012-blink-detection.pdf .
As far as I can remember:
You get B&W current and 100ms ago frames
You do new - old (see 154 in github code)
You apply a threshold then a dilatation filter
You compute contours
If you have a blob with area > to a threshold at the eye location, it means that user blinked eyes
Give a look at the is_blink function at line 316. In his case, he do w * h of blob surrounding box > to a threshold.
In fact it use difference between eye/skin color. In Github implementation, threshold > 5 is used.
What I did was that I converted the eye region from RGB to HSV and applied skin detection. I found out the range of skin color in HSV. If the percentage of skin pixels is greater than threshold value that means Eye is close otherwise it is open. Though there is still some accuracy issue due to amount of light present. Thank you all for giving me a start :)
Generally there is no obvious solution for this problem, but the number of approaches is quite big, so i'm sure that after a bit of serching you will find something good enough for you. For example you can use algorithm which i mentioned here (there is a link to this question in "Related" btw - check other link from this group as well).
i have problem with detection road lanes with my phone.
i wrote some code for road lanes detection, but him not working for me.
From camera get modifications from normal view to BGR colors and try use GausianBlur and Canny, but i think i not good draw lanes for detection.
Maybe some people have another idea how detection road lanes with OpenCV?
Mat mYuv = new Mat(height + height / 2, width, CvType.CV_8UC1);
Mat mRgba = new Mat(height + height / 2, width, CvType.CV_8UC1);
Mat thresholdImage = new Mat(height + height / 2, width, CvType.CV_8UC1);
mYuv.put(0, 0, data);
Imgproc.cvtColor(mYuv, mRgba, Imgproc.COLOR_YUV420p2BGR, 4);
//convert to grayscale
Imgproc.cvtColor(mRgba, thresholdImage, Imgproc.COLOR_mRGBA2RGBA, 4);
// Perform a Gaussian blur (convolving in 5x5 Gaussian) & detect edges
Imgproc.GaussianBlur(mRgba, mRgba, new Size(5,5), 2.2, 2);
Imgproc.Canny(mRgba, thresholdImage, VActivity.CANNY_MIN_TRESHOLD, VActivity.CANNY_MAX_THRESHOLD);
Mat lines = new Mat();
double rho = 1;
double theta = Math.PI/180;
int threshold = 50;
//do Hough transform to find lanes
Imgproc.HoughLinesP(thresholdImage, lines, rho, theta, threshold, VActivity.HOUGH_MIN_LINE_LENGTH, VActivity.HOUGH_MAX_LINE_GAP);
for (int x = 0; x < lines.cols() && x < 1; x++){
double[] vec = lines.get(0, x);
double x1 = vec[0],
y1 = vec[1],
x2 = vec[2],
y2 = vec[3];
Point start = new Point(x1, y1);
Point end = new Point(x2, y2);
Core.line(mRgba, start, end, new Scalar(255, 0, 0), 3);
}
This approach is fine and I've done something similar, not for road line detection but I did notice that it could be used for that purpose. Some comments:
Not sure why you do:
Imgproc.cvtColor(mRgba, thresholdImage, Imgproc.COLOR_mRGBA2RGBA, 4);
as 1. the comment say convert to greyscale, which is a single channel and 2. thresholdImage will get overwritten with the call to Canny later. You just need to dimension thresholdImage with:
thresholdImage = new Mat(mRgba.size(), CvType.CV_8UC1);
What are your parameter values to the call to Canny? I played about with mine considerably and ended up with values like: threshold1 = 441, threshold2 = 160, aperture = 3.
Likewise Imgproc.HoughLinesP: I use Imgproc.HoughLines rather than Imgproc.HoughLinesP with parameters: threshold = 80, minLen = 30, maxLen = 10.
Also have a look at:
for (int x = 0; x < lines.cols() && x < 1; x++){
&& x < 1 means you will only take the first line that the call to HoughLinesP returns. I'd suggest you remove this and use some other criteria to reduce the number of lines; for example, I was interesting in only horizontal and vertical lines so I used atan2 to calculate line angles and exclude those that deviate too much.
UPDATE
Here is how I get the angle of a line. Assuming coordinates of one point is (x1,y1) and the other (x2, y2) then to get the angle:
double lineAngle = Math.atan2(y2 - y1, x2 - x1);
this should return an angle in radians between -PI/2 and PI/2
With regard Canny parameters then I would experiment - I set up onTouch so that I could adjust the threshold values by touching certain parts of the screen to see the effects in realtime. Note that aperture is rather disappointing parameter: it seems to only like odd values 3, 5 and 7 and 3 is the best that I've found.
Something like in the onTouch method:
int w = mRgba.width();
int h = mRgba.height();
float x = event.getX();
float y = event.getY();
if ((x < w / 3) && (y < h / 2)) t1 += 20;
if ((x < w / 3) && (y >= h / 2)) t1 -= 20;
if ((x > 2 * w / 3) && (y < h / 2)) t2 += 20;
if ((x > 2 * w / 3) && (y >= h / 2)) t2 -= 20;
t1 and t2 being the threshold values passed to the Canny call.