Direct2D Border Around Text - delphi

For better visual appearance want to draw a black border around my text.
Currently i am drawing the same text 5 times.
If i want to draw the text on x = 5, y = 10 i would draw the text one time on the actual position.
Then i would draw the same text in black color with slightly other positions.
x = 4, y = 10
x = 5, y = 9
...
I can only imagine that this is bad performance wise. Or is this the correct way?

I never did it the correct way myself, but it seems here they did it: http://www.codeproject.com/Articles/376597/Outline-Text-With-DirectWrite

I do that too. But I suddenly realise there might be a better way (have not tried it yet): first draw in black with a slightly bigger size, and draw again in white with preferred size. Worth a try? Let me know how that goes.

Related

Curved Path2D becomes straight when increasing stroke size

I have this strange problem with Java2D. I have a Path2D.Double that I want to draw, but depending on the stroke size, all segments are drawn correctly (curved) but when the stroke size is greater or equal than 0.00005d the segments are drawn straight. As you can see, the only parameter I'm changing is the stroke size. What am I doing wrong?
BasicStroke basicStroke1 = new BasicStroke(.00004f, CAP_ROUND, JOIN_ROUND);
g2draw.setStroke(basicStroke1);
g2draw.draw(path);
BasicStroke basicStroke2 = new BasicStroke(.00006f, CAP_ROUND, JOIN_ROUND);
g2draw.setStroke(basicStroke2);
g2draw.draw(path);
And here a picture with the result of this code:
Turns out the error seems to be rounding errors when transforming user coordinates to screen coordinates, when the scale difference is big (or not so big...). It's an odd behaviour of Java2D. Switched to JavaFX and the problem disappeared.

Wrong result using function fillPoly in opencv for very large images

I have a hard time solving the issue with mask creation.My image is large,
40959px X 24575px and im trying to create a mask for it.
I noticed that i dont have a problem for images up to certain size(I tested about 33000px X 22000px), but for dimensions larger than that i get an error inside my mask(Error is that it gets black in the middle of the polygon and white region extends itself to the left edge.Result should be without black area inside polygon and no white area extending to the left edge of image).
So my code looks like this:
pixel_points_list = latLonToPixel(dataSet, lat_lon_pairs)
print pixel_points_list
# This is the list im getting
#[[213, 6259], [22301, 23608], [25363, 22223], [27477, 23608], [35058, 18433], [12168, 282], [213, 6259]]
image = cv2.imread(in_tmpImgFilePath,-1)
print image.shape
#Value of image.shape: (24575, 40959, 4)
mask = np.zeros(image.shape, dtype=np.uint8)
roi_corners = np.array([pixel_points_list], dtype=np.int32)
print roi_corners
#contents of roi_corners_array:
"""
[[[ 213 6259]
[22301 23608]
[25363 22223]
[27477 23608]
[35058 18433]
[12168 282]
[ 213 6259]]]
"""
channel_count = image.shape[2]
ignore_mask_color = (255,)*channel_count
cv2.fillPoly(mask, roi_corners, ignore_mask_color)
cv2.imwrite("mask.tif",mask)
And this is the mask im getting with those coordinates(minified mask):
You see that in the middle of the mask the mask is mirrored.I took those points from pixel_points_list and drawn them on coordinate system and im getting valid polygon, but when using fillPoly im getting wrong results.
Here is even simpler example where i have only 4(5) points:
roi_corners = array([[ 213 6259]
[22301 23608]
[35058 18433]
[12168 282]
[ 213 6259]])
And i get
Does anyone have a clue why does this happen?
Thanks!
The issue is in the function CollectPolyEdges, called by fillPoly (and drawContours, fillConvexPoly, etc...).
Internally, it's assumed that the point coordinates (of integer type int32) have meaningful values only in the 16 lowest bits. In practice, you can draw correctly only if your points have coordinates up to 32768 (which is exactly the maximum x coordinate you can draw in your image.)
This can't be considered as a bug, since your images are extremely large.
As a workaround, you can try to scale your mask and your points by a given factor, fill the poly on the smaller mask, and then re-scale the mask back to original size
As #DanMaĆĄek pointed out in the comments, this is in fact a bug, not fixed, yet.
In the bug discussion, there is another workaround mentioned. It consists on drawing using multiple ROIs with size less than 32768, correcting coordinates for each ROI using the offset parameter in fillPoly.

Eliminating various backgrounds from image and segmenting object?

Let say I have this input image, with any number of boxes. I want to segment out these boxes, so I can eventually extract them out.
input image:
The background could anything that is continuous, like a painted wall, wooden table, carpet.
My idea was that the gradient would be the same throughout the background, and with a constant gradient. I could turn where the gradient is about the same, into zero's in the image.
Through edge detection, I would dilate and fill the regions where edges detected. Essentially my goal is to make a blob of the areas where the boxes are. Having the blobs, I would know the exact location of the boxes, thus being able to crop out the boxes from the input image.
So in this case, I should be able to have four blobs, and then I would be able to crop out four images from the input image.
This is how far I got:
segmented image:
query = imread('AllFour.jpg');
gray = rgb2gray(query);
[~, threshold] = edge(gray, 'sobel');
weightedFactor = 1.5;
BWs = edge(gray,'roberts');
%figure, imshow(BWs), title('binary gradient mask');
se90 = strel('disk', 30);
se0 = strel('square', 3);
BWsdil = imdilate(BWs, [se90]);
%figure, imshow(BWsdil), title('dilated gradient mask');
BWdfill = imfill(BWsdil, 'holes');
figure, imshow(BWdfill);
title('binary image with filled holes');
What a very interesting problem! Here's my solution in an attempt to solve this problem for you. This is assuming that the background has the same colour distribution throughout. First, transform your image from RGB to the HSV colour space with rgb2hsv. The HSV colour space is an ideal transform for analyzing colours. After this, I would look at the saturation and value planes. Saturation is concerned with how "pure" the colour is, while value is the intensity or brightness of the colour itself. If you take a look at the saturation and value planes for the image, this is what is shown:
im = imread('http://i.stack.imgur.com/1SGVm.jpg');
out = rgb2hsv(im);
figure;
subplot(2,1,1);
imshow(out(:,:,2));
subplot(2,1,2);
imshow(out(:,:,3));
This is what I get:
By taking a look at some locations in the gray background, it looks like the majority of the saturation are less than 0.2 as well as the elements in the value plane are greater than 0.3. As such, we want to find the opposite of those pixels to get our objects. As such, we find those pixels whose saturation is greater than 0.2 or those pixels with a value that is less than 0.3:
seg = out(:,:,2) > 0.2 | out(:,:,3) < 0.3;
This is what we get:
Almost there! There are some spurious single pixels, so I'm going to perform an opening with imopen with a line structuring element.
After this, I'll perform a dilation with imdilate to close any gaps, then use imfill with the 'holes' option to fill in the gaps, then use erosion with imerode to shrink the shapes back to their original form. As such:
se = strel('line', 3, 90);
pre = imopen(seg, c);
se = strel('square', 20);
pre2 = imdilate(pre, se);
pre3 = imfill(pre2, 'holes');
final = imerode(pre3, se);
figure;
imshow(final);
final contains the segmented image with the 4 candy boxes. This is what I get:
Try resizing the image. When you make it smaller, it would be easier to join edges. I tried what's shown below. You might have to tune it depending on the nature of the background.
close all;
clear all;
im = imread('1SGVm.jpg');
small = imresize(im, .25); % resize
grad = (double(imdilate(small, ones(3))) - double(small)); % extract edges
gradSum = sum(grad, 3);
bw = edge(gradSum, 'Canny');
joined = imdilate(bw, ones(3)); % join edges
filled = imfill(joined, 'holes');
filled = imerode(filled, ones(3));
imshow(label2rgb(bwlabel(filled))) % label the regions and show
If you have a recent version of MATLAB, try the Color Thresholder app in the image processing toolbox. It lets you interactively play with different color spaces, to see which one can give you the best segmentation.
If your candy covers are fixed or you know all the covers that are coming into the scene then Template matching is best for this. As it is independent of the background in the image.
http://docs.opencv.org/doc/tutorials/imgproc/histograms/template_matching/template_matching.html

How to draw an effect (Gloss with metallic lustre) on concentric circle such as following?

I referred to following article. What I actually need to draw is concentric/ Concrete circles with an effect as shown in image below.
I am finding it difficult to a) Draw the white streaks radially b) Find some key terms to search for related articles to proceed further on this.
Any hint or link to read about this will be of great help.
Try these
Metallic Knob
Metallic Knob 2
http://maniacdev.com/2012/06/ios-source-code-example-making-reflective-metallic-buttons-like-the-music-app
This is a tutorial on making reflective metal buttons. You can apply the techniques from the source code to whatever object you're trying to make. The source code is found here on github. I just googled "ios objective c metal effect" because that's what you're trying to do, right? The metal effect appears in concentric circles and changes as you tilt your phone, just as the iOS6 music slider does.
I don't have any code for you but the idea is actually quite simple. You're drawing a number of lines radiating from a single, central point (say 50,50) to four different sets of points. First set is for x = 0 to 100, y = 0. Second set is for y = 0 to 100, x = 0. Third set is for x = 0 to 100, y = 100. Fourth set is for y = 0 to 100, x = 100. And for each step you need to either change the colour from white to black or white to grey in increments or use a look up table with your colour values in it.

Corona SDK: fill up a bar from left to right

I'm learning Corona SDK and am new to lua as well (i mainly do ruby and some javascript).
I have a bar that i want to fill up as the user does stuff. I've set it up as follows:
--outer rectangle
powerBar = display.newRect(210, 6, 24, 9)
powerBar.strokeWidth = 1
powerBar:setStrokeColor(254,203,50)
powerBar:setFillColor(0,0,0,0)
--inner rectangle which fills up
powerBarFill = display.newRect(211,7,0,7)
powerBarFill:setFillColor(234,183,30)
When the "stuff" happens, i add 1 to powerBarFill.width, which i thought would make it grow from left to right. But, it's actually growing out from the centre, ie its x is in the centre and the width extends either side from that.
Whats the best way to keep the left side static and grow the right side? Can i set it so that it's x position is actually on the left hand side rather than in the middle? Seems like that might do it.
cheers in advance
I've run into this problem as well when creating a progress bar. The problem is with the rect's reference point. The default reference point is in the center of an object, as you've noticed. You can use object:setReferencePoint() to change it. I believe you want to use the display.BottomLeftReferencePoint value:
powerBar:setReferencePoint(display.BottomLeftReferencePoint)
Keep in mind that you have to set this value before you set your x,y values. So in your case you'll need to set the reference point after creating the rectangle, and then assign values to x,y again (even though you already did this in the newRect constructor):
powerBar = display.newRect(210, 6, 24, 9)
powerBar:setReferencePoint(display.BottomLeftReferencePoint)
powerBar.x, powerBar.y = 210, 6
If it's width is from the X position on both sides:
1) It should start at:
Centre - (Width when it's full / 2)
2) Every frame, add:
incrs = 1 --Amount to increase by
width = width + incrs
x = x + incrs / 2

Resources