OpenCV Python: Window Size and Mouse Events Coordinates - python

I'm trying to use mouse events and store the coordinates over which the cursor browsed. The problem is that my images are very small, 96x96 pixels and OpenCV chooses a window size that has bigger width than my images. So my image only takes the left side of the window. But the coordinates that are recognized by OpenCV correspond to the window size, so if I move the cursor to the middle of the window, only then are coordinates on the image itself marked at the middle. E.g. in this image the cursor was placed on the middle of the window and not the image:
I tried using the WindowResize function, but for some reason it does not work with images of such a small size, I'm assuming that this is the smallest window size in OpenCV.
Does anybody have any idea of how to make the mouse coordinates actually correspond to the coordinates in the image itself and not the window, or how to make the window size correspond exactly to the size of the image with very small images (96x96)?

I think it can be done by Scaling up your image size.
Here is some python code.
scaleFactor = 10
rows, cols = img.shape[:2]
img = cv2.resize(img, (scaleFactor*cols, scaleFactor*rows), interpolation=cv2.INTER_LINEAR)
Then get mouse position and scale down. ( pseudo code...)
px, py = getMouseClickPosition()
px /= scaleFactor
py /= scaleFactor

Related

What happens to pixels when an image is resized?

I have this original image of size 800 x 600px
What I have to do is to resize the image to 625 x 480px and filter all the land areas. I have found that the BGR values of the land part is (95,155,212). This is the code I used to filter all the and areas:
image[np.where((image == [95,155,212]).all(axis = 2))] = [0,0,0]
If I resize first, then filter, here is the output:
If I filter first then resize, I get my desired output:
So my first question is what happened to the image's pixels when it is resized?
I have this original image of size 712 x 480px
When I applied filtering to remove the land area, I get an output like the second image from the top. 2nd question, is there any way for me to fix this problem?
most likely the resizing changes the border colors to something between land color and black outline.
This screws up your filter because you need higher ranges for land color and also the border line color (Black) can have color artifacts. These artifact are what is left after filtering in your example. If you pick their colors they should be outside your selected range.
How to repair?
use nearest neighbor resizing
this will left the colors as are but the resized image is not as pretty ...
change filters to handle close colors not just range of color
so change to something like flood fill and fill all pixels that do not differ too much from each other. You need 2 thresholds for this:
absolute (is the color range total big one)
relative (is the max change of neighboring pixels small one)
now just recolor the resized image or change the filter function to this ...
Image sizes onscreen and in print
The size of an image when you view it onscreen is different from its size when you print it. If you understand these differences, you can develop a better understanding of which settings to change when you resize an image.
Screen size
The screen resolution of your monitor is the number of pixels it can display. For example, a monitor with a screen resolution of 640 x 480 pixels displays 640 pixels for the width and 480 pixels for the height. There are several different screen resolutions you can use, and the physical size of the monitor screen usually determines the resolutions available. For example, large monitors typically display higher resolutions than small monitors because they have more pixels.
Image size onscreen
Images are of a fixed pixel size when they appear on your monitor. Your screen resolution determines how large the image appears onscreen. A monitor set to 640 x 480 pixels displays fewer pixels than a monitor displaying 1024 x 768 pixels. Therefore, each of the pixel on the 640 x 480 pixel monitor is larger than each pixel displayed on the 1024 x 768 pixel monitor.
A 100 x 100-pixel image uses about one-sixth of the screen at 640 x 480, but it takes up only about one-tenth of the screen at 1024 x 768. Therefore, the image looks smaller at 1024 x 768 pixels than at 640 x 480 pixels
The Following Parameters change when you resize an image
Pixel dimensions: The width and height of the image.
Image size :
Document size: Physical size of the image when printed, including a width and height.
Image resolution when printed: This value appears in pixels per inch or pixels per centimeter.
In Photoshop the physical size, resolution, and pixel dimensions of an image are calculated as follows:
Physical size = resolution x pixel dimensions
Resolution = physical size / pixel dimensions
Pixel dimensions = physical size / resolution
For more info on this you can check Adobe's Document on Image resizing

Find upper left of image after resizing to fit screen

I have a problem I haven't been able to figure out-
Say I have an image of arbitrary dimensions. I resize it so that it fits inside 1024x768 while keeping the aspect ratio. I center it on the screen. After doing this, how can I find where the upper left corner will end up?
So, if the image is wider than it is tall, we end up with something like
The green rectangle started at a different size. It was resized to fit the pink rectangle. I want to find the upper left corner of the green rectangle.
I wrote a bunch of notes and drew a bunch of diagrams, but I'm getting all the wrong answers. Can someone explain how to do this? I'm using python 2.7
Let w,h be the size of your image.
To fit the width of 1024, we must scale the image by:
>>> r=1024./w
However, if the image is taller, after scaling it by r, its height won't fit the screen, so in this case the scaling factor is:
>>> if h*r > 768: r=768./h
The coordinate of the upper left corner of the scaled image is:
>>> (1024-w*r)*0.5,(768-h*r)*0.5
Edit:
A handy function to compute the topleft point (works in Python 2.x as well):
def topLeft(w,h,screenw=1024,screenh=768):
r=float(screenw)/float(w)
if h*r > screenh: r=float(screenh)/float(h)
return (screenw-w*r)*0.5,(screenh-h*r)*0.5

Python fit rectangle picture in squared area

I would like to use Python (and the PIL library) to resize a picture (eventually with width > height or height > width) in a fixed size, let's say (144px * 144px).
I've already found topics about cropping the picture, but I would like to :
Find the biggest side of the picture
Do a thumbnail of the picture with biggest side = 144px and the other side = a ratio
Center the smallest side
Fill the borders of the smallest side with a transparent background so that the final picture is (144px * 144px)
Any ideas on how to do that? For the two first points I would use :
image = PIL.Image.open(pic)
image.thumbnail((144,144), PIL.Image.BILINEAR)
But then I'm blocked. Thanks!

How to convert wx.GetMousePosition co-ordinates to fit in a DC

I'm creating a photo viewer which the user can use to tag images like in facebook. Once the image is clicked on to be tagged, I use wx.GetMousePosition to find the position where the mouse was clicked on the image.I then create a wx.MemoryDC of the image which the user has tagged so that I can draw the tags on the image using dc.DrawRectangle.
Below is the code for drawing onto the image:
I'm using wxPython by the way
W=495 #Position of mouse (y)
H=205 #Position of mouse (x)
dc = wx.MemoryDC()
dc.SelectObject(bitImg)#name of bitmap image
dc.SetPen(wx.Pen('#FF0000'))
#dc.SetBrush(wx.Brush('#aaffff'))
dc.SetBrush(wx.TRANSPARENT_BRUSH)
dc.DrawRectangle(W, H, 20, 20)# Drawing the rectangle using the W and H
# for the position
dc.SelectObject(wx.NullBitmap)
The first two lines are the X and Y co-ordinates which I receive from wx.GetMousePosition. This is the position of a tag on one of the images. These points W and H however do not show on the image when I draw the rectangle as they are too big and don't show on the screen. If I set W and H both to 90 it will draw a small square on the image.
So how can I convert these wx.GetMousePosition co-ordinates so that they fit in the 'dc'? or any other suggestions on getting the mouse co-ordinates?
wx.GetMousePosition will return co-ordinates for the mouse on the screen which will either be in the wrong place in the image, or likely off the edge of the image as you're seeing.
One way you can convert these co-ordinates is to pass them to the panel the image is on, panel.ScreenToClient(wx.GetMousePosition()) which will convert them into co-ordinates relative to the top left of the panel.

Python image mirroring

I've been making a picture mirroring in horizontal and vertical axes. Now I'm going to make the diagonal.
I had done the hori and verti width two for loops which in the hori scenario loops through all the pixels in the height and only the half of the pixels in the width. Then it gets the color of the pixel and set the same color to the pixel on the other side. Going from the getWidth(pic) to the center.
Then I have my mirror in the middle of the pic. How to do the diagonal way?
Edit:
img_src = makePicture(pickAFile())
W = getWidth(img_src)
H = getHeight(img_src)
for x in range(W):
for y in range(H):
p = getPixel(img_src, x, y)
colorInSrc = getColor( getPixel(img_src, x, y) )
destPixel = getPixel(img_src, H-y-1, W-x-1)
setColor(destPixel, colorInSrc)
Using PIL (the Python Imaging Library) this is a relatively straightforward task. Notice however, that the output image is square -- thus not the same size as the original image.
Here is the code:
from PIL import Image, ImageDraw
# load the image, create the mirrored image, and the result placeholder
img = Image.open('img.png')
mirror = img.transpose(Image.FLIP_LEFT_RIGHT).transpose(Image.ROTATE_90)
sz = max(img.size + mirror.size)
result = Image.new(img.mode, (sz,sz))
result.paste(img, (0,0)+img.size)
# now paste the mirrored image, but with a triangular binary mask
mask = Image.new('1', mirror.size)
draw = ImageDraw.Draw(mask)
draw.polygon([0,0,0,sz,sz,sz], outline='white', fill='white')
result.paste(mirror, (0,0)+mirror.size, mask)
# clean up and save the result
del mirror, mask, draw
result.save('result.png')
If I understood correctly what you need is to "flip" the image by a diagonal. Since there are two of them I'll presume that you mean the one that goes from left bottom to right top.
In order to flip by this diagonal you need to transform each row from the source in columns in the destination. The left part of the rows will become the bottom part of the new columns. Also the topmost row will become the rightmost column. You will need to do this pixel by pixel on the whole image. Also keep in mind that the width and height of the image will be swapped.
Edit: A small example. Say you start with an image 5 pixels wide and 3 pixels high (5x3). You will need to create a new blank image 3 pixels wide and 5 pixels high.
If you start pixel numbering from left top corner with (0,0), then this pixel will end up at (2,4) in the new image, pixel (1,0) will end at (2,3) and so on.
If your original width and height are W and H then you should use something like this:
for x in xrange(W):
for y in xrange(H):
p = img_src.getpixel(x, y)
img_dest.setpixel(H-y-1, W-x-1)
This should work, but is not tested.
It's not really an Python question, is it?
The easiest solution would be to first mirror horizontal and then vertical.
Another one would be to switch pixel rows with columns.
Or to do your algorithm but switch the pixels from left-top to bottom-right...
Here's how to mirror diagonally in JES; It only works for a square image though:
def mirrorDiagonal(picture):
for sourceX in range(0,getWidth(picture)):
for sourceY in range (0,getHeight(picture)):
pex=getPixel(picture,sourceY,sourceX)
pix=getPixel(picture, sourceX,sourceY)
color=getColor(pix)
setColor(pex,color)
show(picture)

Categories

Resources