OpenCV & Python - Image too big to display
Asked Answered
M

13

129

I have an image that is 6400 × 3200, while my screen is 1280 x 800. Therefore, the image needs to be resized for display only. I am using Python and OpenCV 2.4.9. According to OpenCV Documentation,

If you need to show an image that is bigger than the screen resolution, you will need to call namedWindow("", WINDOW_NORMAL) before the imshow.

That is what I am doing, but the image is not fitted to the screen, only a portion is shown because it's too big. I've also tried with cv2.resizeWindow, but it doesn't make any difference.

import cv2
cv2.namedWindow("output", cv2.WINDOW_NORMAL)        # Create window with freedom of dimensions
# cv2.resizeWindow("output", 400, 300)              # Resize window to specified dimensions
im = cv2.imread("earth.jpg")                        # Read image
cv2.imshow("output", im)                            # Show image
cv2.waitKey(0)                                      # Display the image infinitely until any keypress
Murielmurielle answered 3/2, 2016 at 15:14 Comment(6)
you should be able to resize image window by pointing cursor to the window bordersFrisch
thanks for your reply, but when I do that, it resizes the window but not the image (the image is not fully displayed). And even if it worked, it's still not ideal since I have to drag the borders many times to finally fit it on the screen, and also this is aimed to be reading continuously from a webcam, I don't want the user to be resizing the window manually.Murielmurielle
Then just resize the image you're showing to your desired dimensionSelfinduction
Thanks, @Miki, I decided to do that. I had not done that before because OpenCV documentation claims to fit it to the screen automatically as in the link I provided, but that was not happening and that was what I wanted to solve. But resizing is fine too, I guess.Murielmurielle
I think you should do something like thisTrafficator
This worked great for me. I encountered a strange issue where the named window dimensions are preserved after the program ends. If manipulate the window and then I run the program again, the window has the same skewed dimensions. Any idea how to reset the dimensions on each run?Luralurch
M
152

Although I was expecting an automatic solution (fitting to the screen automatically), resizing solves the problem as well.

import cv2
cv2.namedWindow("output", cv2.WINDOW_NORMAL)    # Create window with freedom of dimensions
im = cv2.imread("earth.jpg")                    # Read image
imS = cv2.resize(im, (960, 540))                # Resize image
cv2.imshow("output", imS)                       # Show image
cv2.waitKey(0)                                  # Display the image infinitely until any keypress
Murielmurielle answered 3/2, 2016 at 17:2 Comment(2)
Yes, my mistake, I have it correctly on my code, but not here. ThanksMurielmurielle
WINDOW_NORMAL already causes the window to be resizable. there is absolutely not need to have an additional resize call.Polycythemia
M
59

The other answers perform a fixed (width, height) resize. If you wanted to resize to a specific size while maintaining aspect ratio, use this

def ResizeWithAspectRatio(image, width=None, height=None, inter=cv2.INTER_AREA):
    dim = None
    (h, w) = image.shape[:2]

    if width is None and height is None:
        return image
    if width is None:
        r = height / float(h)
        dim = (int(w * r), height)
    else:
        r = width / float(w)
        dim = (width, int(h * r))

    return cv2.resize(image, dim, interpolation=inter)

Example

image = cv2.imread('img.png')
resize = ResizeWithAspectRatio(image, width=1280) # Resize by width OR
# resize = ResizeWithAspectRatio(image, height=1280) # Resize by height 

cv2.imshow('resize', resize)
cv2.waitKey()
Mattern answered 27/9, 2019 at 2:2 Comment(0)
D
24

Use this for example:

cv2.namedWindow('finalImg', cv2.WINDOW_NORMAL)
cv2.imshow("finalImg",finalImg)
Dwarfism answered 16/9, 2020 at 7:4 Comment(2)
This does not work :(Cense
Just using this flag worked, however combining with other flags as cv2.WINDOW_NORMAL | cv2.WINDOW_KEEPRATIO | cv2.WINDOW_FULLSCREEN fails.Delgadillo
F
23

The only way resizeWindow worked for me was to have it after imshow. This is the order I'm using:

# Create a Named Window
cv2.namedWindow(win_name, cv2.WINDOW_NORMAL)

# Move it to (X,Y)
cv2.moveWindow(win_name, X, Y)
    
# Show the Image in the Window
cv2.imshow(win_name, image)
    
# Resize the Window
cv2.resizeWindow(win_name, width, height)
    
# Wait for <> miliseconds
cv2.waitKey(wait_time)
Flagman answered 7/3, 2021 at 2:0 Comment(1)
This has worked for me. Thank youMayworm
L
11

In OpenCV, cv2.namedWindow() just creates a window object, but doesn't resize the original image. You can use cv2.resize(img, resolution) to solve the problem.

Here's what it displays, a 740 * 411 resolution image. The original image

image = cv2.imread("740*411.jpg")
cv2.imshow("image", image)
cv2.waitKey(0)
cv2.destroyAllWindows()

Here, it displays a 100 * 200 resolution image after resizing. Remember the resolution parameter use column first then is row.

Image after resizing

image = cv2.imread("740*411.jpg")
image = cv2.resize(image, (200, 100))
cv2.imshow("image", image)
cv2.waitKey(0)
cv2.destroyAllWindows()
Lymphoid answered 8/5, 2018 at 16:0 Comment(4)
Welcome to Stackoverflow.com Please use formatting tools within post form to make your post more readable. Image should be uploaded as image not a linkForsythe
@Prateek Hi, I was trying to insert images in my post but seems it always comes with a link instead of images.Lymphoid
image == [![link-to-image]][n] and url= [link](link)Forsythe
Got it. Thank you very muchLymphoid
G
6

This code will resize the image so that it can retain it's aspect ratio and only ever take up a specified fraction of the screen area.

It will automatically adjust depending on your screen size and the size of the image.

Use the area variable to change the max screen area you want the image to be able to take up. The example shows it displayed at quarter the screen size.

import cv2
import tkinter as tk
from math import *

img = cv2.imread("test.jpg")
area = 0.25

h, w = img.shape[:2]
root = tk.Tk()
screen_h = root.winfo_screenheight()
screen_w = root.winfo_screenwidth()
vector = sqrt(area)
window_h = screen_h * vector
window_w = screen_w * vector

if h > window_h or w > window_w:
    if h / window_h >= w / window_w:
        multiplier = window_h / h
    else:
        multiplier = window_w / w
    img = cv2.resize(img, (0, 0), fx=multiplier, fy=multiplier)

cv2.imshow("output", img)
cv2.waitKey(0)

I've also made a similar function where area is still a parameter but so is window height and window width.

If no area is input then it will use a defined height and width (window_h, window_w) of the window size you would like the image to fit inside.

If an input is given for all parameters then 'area' is prioritised.

import cv2
import tkinter as tk
from math import *

def resize_image(img, area=0.0, window_h=0, window_w=0):
    h, w = img.shape[:2]
    root = tk.Tk()
    screen_h = root.winfo_screenheight()
    screen_w = root.winfo_screenwidth()

    if area != 0.0:
        vector = math.sqrt(area)
        window_h = screen_h * vector
        window_w = screen_w * vector

    if h > window_h or w > window_w:
        if h / window_h >= w / window_w:
            multiplier = window_h / h
        else:
            multiplier = window_w / w
        img = cv2.resize(img, (0, 0), fx=multiplier, fy=multiplier)

    return img

# using area
initial_image = cv2.imread("test.jpg")
resized_image = resize_image(initial_image, area=0.25))
cv2.imshow("output", resized_image)
cv2.waitKey(0)

# using window height and width
initial_image = cv2.imread("test.jpg")
resized_image = resize_image(initial_image, window_h = 480, window_w = 270))
cv2.imshow("output", resized_image)
cv2.waitKey(0)
Galen answered 27/5, 2021 at 8:7 Comment(0)
P
4

Looks like opencv lib is pretty sensitive to parameters passed to the methods. The following code worked for me using opencv 4.3.0:

win_name = "visualization"  #  1. use var to specify window name everywhere
cv2.namedWindow(win_name, cv2.WINDOW_NORMAL)  #  2. use 'normal' flag
img = cv2.imread(filename)
h,w = img.shape[:2]  #  suits for image containing any amount of channels
h = int(h / resize_factor)  #  one must compute beforehand
w = int(w / resize_factor)  #  and convert to INT
cv2.resizeWindow(win_name, w, h)  #  use variables defined/computed BEFOREHAND
cv2.imshow(win_name, img)
Patrilocal answered 1/12, 2020 at 9:58 Comment(0)
M
3

Try this:

image = cv2.imread("img/Demo.jpg")
image = cv2.resize(image,(240,240))

The image is now resized. Displaying it will render in 240x240.

Malinger answered 7/10, 2018 at 13:36 Comment(2)
This is already in the accepted answer, I'm confused why you added it as a new answer?Haleakala
I think user doesnt want to resize actual image, rather resize display windowLeslileslie
S
1

The cv2.WINDOW_NORMAL option works correctly but the first time it displays the window in an standard size.

If you resize the window like any other windows in your computer, by position the mouse over the edge of the window you want to resize and then drag the mouse to the position you want. If you do this to both width and height of the window to the size you want to obtain.

The following times you refresh the window, by executing the code, OpenCV will generate the window with the size of the last time it was shown or modified.

Sixty answered 24/5, 2021 at 17:33 Comment(2)
Please explain in detail.Egocentric
I tried to explain it better, please confirm me if you now understood it. :)Sixty
S
1

Try this code:

img = cv2.imread("Fab2_0.1 X 1.03MM GRID.jpg", cv2.IMREAD_GRAYSCALE)
image_scale_down = 3
x = (int)(img.shape[0]/image_scale_down)
y = (int)(img.shape[1]/image_scale_down)
image = cv2.resize(img, (x,y))
cv2.imshow("image_title", image)
cv2.waitKey(5000)
cv2.destroyAllWindows()
Salimeter answered 14/9, 2021 at 12:28 Comment(0)
M
0

The most upvote answer is perfect ! I just add my code for those who want some "dynamic" resize handling depending of the ratio.

import cv2
from win32api import GetSystemMetrics

def get_resized_for_display_img(img):
    screen_w, screen_h = GetSystemMetrics(0), GetSystemMetrics(1)
    print("screen size",screen_w, screen_h)
    h,w,channel_nbr = img.shape
    # img get w of screen and adapt h
    h = h * (screen_w / w)
    w = screen_w
    if h > screen_h: #if img h still too big
        # img get h of screen and adapt w
        w = w * (screen_h / h)
        h = screen_h
    w, h = w*0.9, h*0.9 # because you don't want it to be that big, right ?
    w, h = int(w), int(h) # you need int for the cv2.resize
    return cv2.resize(img, (w, h))
Markus answered 2/11, 2021 at 14:22 Comment(0)
C
-2

Try with this code:

from PIL import Image

Image.fromarray(image).show()
Chemosphere answered 10/3, 2020 at 18:6 Comment(0)
H
-2

Try this code

img = cv2.resize(img,(1280,800))
Hexastich answered 6/3, 2022 at 21:18 Comment(1)
Please explain what your code does as well.Colewort

© 2022 - 2024 — McMap. All rights reserved.