Detect change in color of pixel - c++

I'm new to making programs and I have no idea where to really begin.
However I have this simple idea that I want to turn into reality.
I need to find a red pixel in a blue area on screen. The area is a rectangle from
(x = 86)(y = 457) to (x = 770)(y = 641) -- that's just can example.
Then get a list of all the pixels within that region and check if they are a certain color like (Red=186, Blue=10, Green=10)
Then 0.2 seconds later check if those pixels that were red are still red.
Then check again 3 times, every 0.2 seconds.
After that tell the program to wait until those pixels turn blue.
When they do open C:User/User1/documentss/pull.mcs --random file.
I would like to create this thing, but I have no idea how to get all the pixels within a certain region (since there is thousands and doing it manually won't work) then check their color and finally tell the program to open another program.
The picture attached is what I am working on, this red thing moves and I need to first find where it is and then make sure that the pixel stays red. Eventually the thing will sink and I need a program to start.
Thanks for reading and please give me some suggestions.
https://i.stack.imgur.com/EvC6t.png

In case someone else is looking for a solution to a problem like this. This can e accomplished with autohotkey very easily.
"find a red pixel in a blue area on screen. The area is a rectangle from
(x = 86)(y = 457) to (x = 770)(y = 641)"
in this example the red area is irrelevant, we're just looking for the blue pixel
PixelSearch, x, y, 457, 770, 770, 641, 0x0000FF, Fast RGB
if (ErrorLevel = 0){
MsgBox, Found the pixel at %x%,%y%
}
else MsgBox, We did not find the pixel.
Return

Related

Disparity Map Block Matching

I am writing a disparity matching algorithm using block matching, but I am not sure how to find the corresponding pixel values in the secondary image.
Given a square window of some size, what techniques exist to find the corresponding pixels? Do I need to use feature matching algorithms or is there a simpler method, such as summing the pixel values and determining whether they are within some threshold, or perhaps converting the pixel values to binary strings where the values are either greater than or less than the center pixel?
I'm going to assume you're talking about Stereo Disparity, in which case you will likely want to use a simple Sum of Absolute Differences (read that wiki article before you continue here). You should also read this tutorial by Chris McCormick before you read more here.
side note: SAD is not the only method, but it's really common and should solve your problem.
You already have the right idea. Make windows, move windows, sum pixels, find minimums. So I'll give you what I think might help:
To start:
If you have color images, first you will want to convert them to black and white. In python you might use a simple function like this per pixel, where x is a pixel that contains RGB.
def rgb_to_bw(x):
return int(x[0]*0.299 + x[1]*0.587 + x[2]*0.114)
You will want this to be black and white to make the SAD easier to computer. If you're wondering why you don't loose significant information from this, you might be interested in learning what a Bayer Filter is. The Bayer Filter, which is typically RGGB, also explains the multiplication ratios of the Red, Green, and Blue portions of the pixel.
Calculating the SAD:
You already mentioned that you have a window of some size, which is exactly what you want to do. Let's say this window is n x n in size. You would also have some window in your left image WL and some window in your right image WR. The idea is to find the pair that has the smallest SAD.
So, for each left window pixel pl at some location in the window (x,y) you would the absolute value of difference of the right window pixel pr also located at (x,y). you would also want some running value, which is the sum of these absolute differences. In sudo code:
SAD = 0
from x = 0 to n:
from y = 0 to n:
SAD = SAD + absolute_value|pl - pr|
After you calculate the SAD for this pair of windows, WL and WR you will want to "slide" WR to a new location and calculate another SAD. You want to find the pair of WL and WR with the smallest SAD - which you can think of as being the most similar windows. In other words, the WL and WR with the smallest SAD are "matched". When you have the minimum SAD for the current WL you will "slide" WL and repeat.
Disparity is calculated by the distance between the matched WL and WR. For visualization, you can scale this distance to be between 0-255 and output that to another image. I posted 3 images below to show you this.
Typical Results:
Left Image:
Right Image:
Calculated Disparity (from the left image):
you can get test images here: http://vision.middlebury.edu/stereo/data/scenes2003/

extract the shapes made a particular colour in opencv

take this image below
I would like to extract the shapes of the red outline into a separate image. I want to do this because I want to check the convexity of theses shapes for my work. Any advice? I tried split channels but that just removes the red colour from the image.
Since you have drawn the red border by yourself, there is no need to analyze the red component at all. By doing that, you are exactly like someone who take a print screen of txt file and trying to OCR it!
The solution:
cv::BoundingBox around the point of the first red contour.
Get ROI of the rectangle and store it in a separate cv::Mat.
Create a new black(0) cv::Mat with the same header of the previous cv::Mat.
Draw the contour with White(255) using cv::fillPoly.
cv::bitwise_and between the two cv::Mats.
You could try making an image that comprises pixels where red is the dominant colour, for example you would examine every pixel and make a B/W image like this
#define MIN_RED 192
#define MAX_OTHER 64
// each pixel
if (r >= MIN_RED && g <= MAX_OTHER && b <= MAX_OTHER)
c = 1;
else
c = 0;
This would filter out the blues and greens and grays and preserve the bright reds.

Shifting color channels without drawing each channel separately?

I want to draw with Direct2D frames which color channels are shifted on x-axis. I know I could set the composition mode to D2D1_COMPOSITE_MODE_PLUS and draw each color channel separately so I can shift them manually. But I want to know if there is another (maybe more efficient) way of drawing shapes with shifted color channels?
I attached an image which shows what I mean.
(I suggest to open this image in a new tab and zoom in to see the effect better)
The way this is typically done is to sample 3 pixels from the input image at a time, each separated by some amount in the x direction, and combine the red from one, the green from another, and the blue from the third. Unfortunately, I don't know DX2D at all, so I don't know the specifics of how it works there. But if you have a bitmap and a pointer to the pixels, you can simply subtract one (or more) pixels from that pointer, and add one or more pixels to the that pointer and read from those memory locations (being careful to account for image edges). Then pull the channels from the values you've read. For example:
RGBA8* pixel = baseAddressOfImage;
RGBA8* pixelMinus1 = pixel - 1;
RGBA8* pixelPuls1 = pixel + 1;
for each pixel in the output
{
result.red = pixelMinus1->red;
result.green = pixel->green;
result.blue = pixelPlus1->blue;
pixelMinus1++;
pixel++;
pixelPlus1++;
}
Note that you can add or subtract more than 1, but as mentioned above, you have to handle what happens at the edges in those cases.

Determine most visible foreground color [duplicate]

I'm drawing a color selection button and I'm looking for a nice and simple formula to get a good text color (foreground) for a given background color in RGB.
A simple try would be to just take the complement color but this will produce an odd looking button for colors like pure blue or pure red.
Is there something well known that does this?
If it matters at all, I'm using QT.
For maximum legibility, you want maximum brightness contrast without getting into hues which don't work together. The most consistent way to do this is to stick with black or white for the text color. You might be able to come up with more aesthetically pleasing schemes, but none of them will be more legible.
To pick between black or white, you need to know the brightness of the background. This gets a little more complicated, due to two factors:
The perceived brightness of the individual primaries red, green, and blue are not identical. The quickest advice I can give is to use the traditional formula to convert RGB to gray - R*0.299 + G*0.587 + B*0.114. There are lots of other formulas.
The gamma curve applied to displays makes the middle gray value higher than you'd expect. This is easily solved by using 186 as the middle value rather than 128. Anything less than 186 should use white text, anything greater than 186 should use black text.
I'm no expert on programming things related to RGB, but from a designer's perspective, often the most readable color will be just a much lighter (if the background color is dark) or darker (if the background color is light) version of the same shade.
Basically you'd take your RGB values and if they're closer to 0 (dark) you'd push them each up by an equal amount for your foreground color, or vice versa if it's a light BG.
Complement colors can actually be really painful on the eyes for readability.
Leverage an outline for legibility
If by "good text color (foreground)" you intend it for legibility purposes when the user chooses any background colour, you can always produce white text having a black outline. It will be legible on any solid, patterned or gradient background, from black through white and anything in between.
Even if this doesn't hit the mark of your intention, I think it worthwhile posted here because I came looking for similar solutions.
Building on top of Mark's response, here's some Ruby code that'll do the work
rgbval = "8A23C0".hex
r = rgbval >> 16
g = (rgbval & 65280) >> 8
b = rgbval & 255
brightness = r*0.299 + g*0.587 + b*0.114
return (brightness > 160) ? "#000" : "#fff"
You are better off with a high difference in luminosity. In general, colored backgrounds with colored text suck for readability, hurting the eyes over time. Lightly tinted colors (e.g. in HSB, S~10%, B>90%) with black text work fine, or lightly tinted text over a black background. I'd stay away from coloring both. Dark text (b~30%, s>50%) with a subtle coloration over a white background can also be fine. Yellow (amber) text on a deep blue background has excellent readability, as does amber or green on black. This is why old dumbterms (vt100, vt52, etc.) went for these colors.
If you really need to do color-on-color for the 'look', you could reverse both H and B, while pinning saturation at a moderate to low level.
And one last note: if you have a 50% gray background, rethink your interface. You're robbing yourself of half your dynamic range! You're alienating low-visibility users, including anyone over 35...
Color combinations often look terrible when not carefully chosen. Why not use either white or black for the text, depending on the Brightness of the color. (Will need to convert to HSB first.)
Or let the user choose either black or white text.
Or use pre-defined combinations. This is what Google does in their calendar product.
I've been looking for a simailr answer and came across this post and some others that I thought I'd share. According to http://juicystudio.com/services/luminositycontrastratio.php#specify the "Success Criterion 1.4.3 of WCAG 2.0 requires the visual presentation of text and images of text has a contrast ratio of at least 4.5:1" with some exceptions. That site lets you put in foreground and background colors to compute their contrast, although it would be helpful if it would suggest alternatives or ranges.
One of the best sites I've found for visualizing color contrast is http://colorizer.org/ It lets you adjust almost all manner of color scales (RGB, CMYK, etc.) at the same time and then shows you the result on the screen, such as white text on a yellow background.
I usually look at color complements, they also have color complement wheels to help
http://www.makart.com/resources/artclass/cwheel.html
If your color is HSL, flip the Hue by 180 degrees for a decent calculation
I wanted to put #MarkRansom's answer into use and managed to create this snippet:
I got the values From seeing how sRGB converts to CIE XYZ and built upon that.
The script simply tracks the position of the foreground item and it's position regarding the colored background items.
Then based on background luminosity it gradually changes the foreground text color to either black or white.
Open the codepen for full example
https://codepen.io/AndrewKnife/pen/XWBggQq
const calculateLight = (colorItem: number) => {
let c = colorItem / 255.0;
if (c <= 0.03928) {
c /= 12.92;
} else {
c = Math.pow((c + 0.055) / 1.055, 2.4);
}
return c;
};
const calculateLuminosity = (color: RGBColor) => {
return (
0.2126 * calculateLight(color.r) +
0.7152 * calculateLight(color.g) +
0.0722 * calculateLight(color.b)
);
};
const getContrastColor = (color: RGBColor) => {
if (calculateLuminosity(color) > LUMINOSITY_LIMIT) {
return FONT_COLOR_DARK;
}
return FONT_COLOR_LIGHT;
};
I thing that converting to HSV might be the way, but IMO changing hue would look weird. I'd try keeping the hue and fiddling with value and maybe saturation (light red buttons with dark red text ... hm sounds scary :-) ).

transparent colour being shown some of the time

I am using a LPDIRECT3DTEXTURE9 to hold my image.
This is the function used to display my picture.
int drawcharacter(SPRITE& person, LPDIRECT3DTEXTURE9& image)
{
position.x = (float)person.x;
position.y = (float)person.y;
sprite_handler->Draw(
image,
&srcRect,
NULL,
&position,
D3DCOLOR_XRGB(255,255,255));
return 0;
}
According to the book I have the RGB colour shown as the last parameter will not be displayed on screen, this is how you create transparency.
This works for the most part but leaves a pink line around my image and the edge of the picture. After trial and error I have found that if I go back into photoshop I can eliminate the pink box by drawing over it with the pink colour. This can be see with the ships on the left.
I am starting to think that photoshop is blending the edges of the image so that background is not all the same shade of pink though I have no proof.
Can anyone help fix this by programming or is the error in the image?
If anyone is good at photoshop can they tell me how to fix the image, I use png mostly but am willing to change if necessary.
edit: texture creation code as requested
character_image = LoadTexture("character.bmp", D3DCOLOR_XRGB(255,0,255));
if (character_image == NULL)
return 0;
You are loading a BMP image, which does not support transparency natively - the last parameter D3DCOLOR_XRGB(255,0,255) is being used to add transparency to an image which doesn't have any. The problem is that the color must match exactly, if it is off even by only one it will not be converted to transparent and you will see the near-magenta showing through.
Save your images as 24-bit PNG with transparency, and if you load them correctly there will be no problems. Also don't add the magenta background before you save them.
As you already use PNG, you can just store the alpha value there directly from Photoshop. PNG supports transparency out of the box, and it can give better appearance than what you get with transparent colour.
It's described in http://www.toymaker.info/Games/html/textures.html (for example).
Photoshop is anti-aliasing the edge of the image. If it determines that 30% of a pixel is inside the image and 70% is outside, it sets the alpha value for that pixel to 70%. This gives a much smoother result than using a pixel-based transparency mask. You seem to be throwing these alpha values away, is that right? The pink presumably comes from the way that Photoshop displays partially transparent pixels.