I have this picture:
I want to create a mask from this image, to place on top of the original image. The mask I want to obtain is the black part at the top.
I tried to use simpleBlobDetector from OpenCV to try to detect the white part as one big blob. I do not obtain the results I am hoping for and am unsure what to do.
R has been used, but my question is not specifically on how to achieve this in R. The result I have is below the code.
library(Rvision)
x <- simpleBlobDetector(im, min_threshold = 0, max_threshold = 255)
plot(x)
I do not understand why those three black boxes are selected as blobs, while there are a lot more of those black boxes that are not selected.
EDIT: when I add blob_color = 255 so white blobs are searched, nothing is detected.
You can do something like this using OpenCV:
// read input image
Mat inputImg = imread("test1.tif", IMREAD_GRAYSCALE);
// create binary image
Mat binImg;
threshold(inputImg, binImg, 254, 1, THRESH_BINARY_INV);
// compute connected components
Mat labelImg;
connectedComponents(binImg, labelImg, 8, CV_16U);
// compute histogram
Mat histogram;
int histSize = 256;
float range[] = { 0, 256 } ;
const float* histRange = { range };
calcHist(&labelImg, 1, 0, Mat(), histogram, 1, &histSize, &histRange, true, false);
// retrieve maximal population
float maxVal = 0;
int maxIdx;
for (int i=1; i<histSize; ++i) {
if (histogram.at<float>(i) > maxVal) {
maxVal = histogram.at<float>(i);
maxIdx = i;
}
}
// create output mask with bigest population
Mat resImg;
threshold(labelImg, labelImg, maxIdx, 0, THRESH_TOZERO_INV);
threshold(labelImg, resImg, maxIdx-1, 1, THRESH_BINARY);
// write result
imwrite("res.tif", resImg);
And you should obtain something like this:
I think you can convert input to bianry, then extract connected components, compute associated histogram and simply keep (by thresholding) histogram class with highest population
Regards
Related
My goal here is to improve the user experience so that the cursor goes where the user would intuitively expect it to when moving the joystick diagonally, whatever that means.
Consider a joystick that has a different configured speed for each direction.
e.g. Maybe the joystick has a defect where some directions are too sensitive and some aren't sensitive enough, so you're trying to correct for that. Or maybe you're playing an FPS where you rarely need to look up or down, so you lower the Y-sensitivity.
Here are our max speeds for each direction:
var map = {
x: 100,
y: 200,
}
The joystick input gives us a unit vector from 0 to 1.
Right now the joystick is tilted to the right 25% of the way and tilted up 50% of the way.
joystick = (dx: 0.25, dy: -0.50)
Sheepishly, I'm not sure where to go from here.
Edit: I will try #Caderyn's solution:
var speeds = {
x: 100, // max speed of -100 to 100 on x-axis
y: 300, // max speed of -300 to 300 on y-axis
}
var joystick = { dx: 2, dy: -3 }
console.log('joystick normalized:', normalize(joystick))
var scalar = Math.sqrt(joystick.dx*joystick.dx / speeds.x*speeds.x + joystick.dy*joystick.dy / speeds.y*speeds.y)
var scalar2 = Math.sqrt(joystick.dx*joystick.dx + joystick.dy*joystick.dy)
console.log('scalar1' , scalar) // length formula that uses max speeds
console.log('scalar2', scalar2) // regular length formula
// normalize using maxspeeds
var normalize1 = { dx: joystick.dx/scalar, dy: joystick.dy/scalar }
console.log('normalize1', normalize1, length(normalize1))
// regular normalize (no maxpseed lookup)
var normalize2 = { dx: joystick.dx/scalar2, dy: joystick.dy/scalar2 }
console.log('normalize2', normalize2, length(normalize2))
function length({dx, dy}) {
return Math.sqrt(dx*dx + dy*dy)
}
function normalize(vector) {
var {dx,dy} = vector
var len = length(vector)
return {dx: dx/len, dy: dy/len}
}
Am I missing something massive or does this give the same results as regular vector.len() and vector.normalize() that don't try to integrate the maxspeed data at all?
three solutions :
You can simply multiply each component of the input vector by it's respective speed
you can divide the vector itself by sqrt(dx^2/hSpeed^2+dy^2/vSpeed^2)
you can multiply the vector itself by sqrt((dx^2+dy^2)/(dx^2/hSpeed^2+dy^2/vSpeed^2)) or 0 if the input is (0, 0)
the second solution will preserve the vector's direction when the first will tend to pull it in the direction with the greatest max speed. But if the domain of those function is the unit disc, their image will be an ellipse whose radii are the two max speeds
EDIT : the third method does what the second intended to do: if the imput is A, it will return B such that a/b=c/d (the second method was returning C):
The problem is as such:
given an array of N numbers, find two numbers in the array such that they will have a range(max - min) value of K.
for example:
input:
5 3
25 9 1 6 8
output:
9 6
So far, what i've tried is first sorting the array and then finding two complementary numbers using a nested loop. However, because this is a sort of brute force method, I don't think it is as efficient as other possible ways.
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt(), k = sc.nextInt();
int[] arr = new int[n];
for(int i = 0; i < n; i++) {
arr[i] = sc.nextInt();
}
Arrays.sort(arr);
int count = 0;
int a, b;
for(int i = 0; i < n; i++) {
for(int j = i; j < n; j++) {
if(Math.max(arr[i], arr[j]) - Math.min(arr[i], arr[j]) == k) {
a = arr[i];
b = arr[j];
}
}
}
System.out.println(a + " " + b);
}
}
Much appreciated if the solution was in code (any language).
Here is code in Python 3 that solves your problem. This should be easy to understand, even if you do not know Python.
This routine uses your idea of sorting the array, but I use two variables left and right (which define two places in the array) where each makes just one pass through the array. So other than the sort, the time efficiency of my code is O(N). The sort makes the entire routine O(N log N). This is better than your code, which is O(N^2).
I never use the inputted value of N, since Python can easily handle the actual size of the array. I add a sentinel value to the end of the array to make the inner short loops simpler and quicker. This involves another pass through the array to calculate the sentinel value, but this adds little to the running time. It is possible to reduce the number of array accesses, at the cost of a few more lines of code--I'll leave that to you. I added input prompts to aid my testing--you can remove those to make my results closer to what you seem to want. My code prints the larger of the two numbers first, then the smaller, which matches your sample output. But you may have wanted the order of the two numbers to match the order in the original, un-sorted array--if that is the case, I'll let you handle that as well (I see multiple ways to do that).
# Get input
N, K = [int(s) for s in input('Input N and K: ').split()]
arr = [int(s) for s in input('Input the array: ').split()]
arr.sort()
sentinel = max(arr) + K + 2
arr.append(sentinel)
left = right = 0
while arr[right] < sentinel:
# Move the right index until the difference is too large
while arr[right] - arr[left] < K:
right += 1
# Move the left index until the difference is too small
while arr[right] - arr[left] > K:
left += 1
# Check if we are done
if arr[right] - arr[left] == K:
print(arr[right], arr[left])
break
I'm extracting the min from a vector.
Say vector = [0, inf, inf, inf];
ExtractSmallest(vector) = 0;
and then vector = [0, 1, inf, inf];
but now, we've already seen 0. Thus,
ExtractSmallest(vector) = 1;
I represent this in my code by doing nodes.erase(nodes.begin() + smallestPosition);
But, I now realize that erasing is very bad. Is there a way to achieve this without erasing the vectors? Just skipping over the ones we've already seen?
Node* CGraph::ExtractSmallest(vector<Node*>& nodes)
{
int size = nodes.size();
if (size == 0) return NULL;
int smallestPosition = 0;
Node* smallest = nodes.at(0);
for (int i=1; i<size; ++i)
{
Node* current = nodes.at(i);
if (current->distanceFromStart <
smallest->distanceFromStart)
{
smallest = current;
smallestPosition = i;
}
}
nodes.erase(nodes.begin() + smallestPosition);
return smallest;
}
Option 1 You can have an additional vector<bool> on which you iterate in parallel. When you find the smallest element, mark that position in the bool vector as true. Whenever you iterate, skip the positions in both vectors that are marked as true.
Option 2 If order is not important, keep the number of elements removed so far. When you find the minimum, swap positions with the first non-excluded element. On a new iteration, start from the first non-excluded element.
Option 3 If order is not important, sort the array. (this takes O(n*log(n))). Removal will now take O(1) - you just exclude the first non-excluded element.
Option 4 If there are no duplicates, you can keep a std::set on the side with all excluded elements to this point. When you iterate, check whether the current element was already excluded or not.
In the discussion of the colour colorMatrix:bias it reads :
This filter performs a matrix multiplication, as follows, to transform the color vector:
s.r = dot(s, redVector) s.g = dot(s, greenVector) s.b = dot(s, blueVector) s.a = dot(s, alphaVector) s = s + bias
Is there any way to gain access to the data values for the various colour vectors?
The discussion you're referring to, in the C4 documentation, refers to the process that a filter uses for calculating a matrix multiplication. This is actually just a description of what the filter does to the colors in the image when it gets applied.
In fact, what's happening under the hood is that the colorMatrix: method sets up a CIFilter called CIColorMatrix and applies this to a C4Image. Unfortunately the source code for the CIColorMatrix filter isn't provided by Apple.
So, a longwinded answer to your question is:
You can't access color components for pixels in a C4Image through the CIColorMatrix filter. But, the C4Image class has a property called CGImage (e.g. yourC4Image.CGImage) which you can use to get pixel data.
A good, simple technique can be found HERE
EDIT:
I got obsessed last night with this question, and added these two methods to the C4Image class:
Method for loading pixel data:
-(void)loadPixelData {
NSUInteger width = CGImageGetWidth(self.CGImage);
NSUInteger height = CGImageGetHeight(self.CGImage);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
bytesPerPixel = 4;
bytesPerRow = bytesPerPixel * width;
rawData = malloc(height * bytesPerRow);
NSUInteger bitsPerComponent = 8;
CGContextRef context = CGBitmapContextCreate(rawData, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);
CGContextDrawImage(context, CGRectMake(0, 0, width, height), self.CGImage);
CGContextRelease(context);
}
And a method for accessing pixel color:
-(UIColor *)colorAt:(CGPoint)point {
if(rawData == nil) {
[self loadPixelData];
}
NSUInteger byteIndex = bytesPerPixel * point.x + bytesPerRow * point.y;
CGFloat r, g, b, a;
r = rawData[byteIndex];
g = rawData[byteIndex + 1];
b = rawData[byteIndex + 2];
a = rawData[byteIndex + 3];
return [UIColor colorWithRed:RGBToFloat(r) green:RGBToFloat(g) blue:RGBToFloat(b) alpha:RGBToFloat(a)];
}
That's how I would apply the techniques from the other post I mentioned.
I am trying get the count of each series point over specific areas of my plot.
The plot is made up of grids (boxes) and I wish to know the count of each of my series points that is present in each of these boxes. I want to get information like (grid 1 had 2 of series 1, 0 of series 2, 3 of series3, 4 of series 5, etc)
Any help is greatly appreciated.
When you have XYItems you can get the bounds of each item:
final Collection<ChartEntity> entities =
chartpanel.getChartRenderingInfo().getEntityCollection().getEntities();
for (final ChartEntity e : entities) {
if (e instanceof XYItemEntity) {
final XYItemEntity xyItem = (XYItemEntity) e;
final int index = xyItem.getItem();
final int series = xyItem.getSeriesIndex();
Rectangle2D r = e.getArea().getBounds2D();
checkPosition(r); // here you can check if the coordinates are inside your "box"
}
}