Atul Balaji
Atul Balaji

Reputation: 812

Zooming functionality in OpenCV imshow in Windows

In Ubuntu, OpenCV's imshow function has a window where different options such as zoom in, zoom out, pan window, etc, are available, like this:

enter image description here

However, in Windows, these features are absent. I have a particular case where I need to deploy my OpenCV code on Windows, where the user needs to zoom into parts of the image.

Is there any way to access/add these functionalities in Windows also?

Upvotes: 5

Views: 26631

Answers (4)

alias_z
alias_z

Reputation: 1

@mluerig and many others have pointed out the solutions - enable QT in cmake. I am here to share the reason and my solutions.

The reason:

if you go to the highgui module documentation, we will find those functions such as zooming, pixel values are only implemented with Qt GUI.

My solution:

  1. If you are like me, who want to use CUDA support, and other extra modules, you have to build from source with Qt enabled.

  2. if you are not interested in CUDA, but want to go for some extra modules, you can use: conda install libopencv opencv py-opencv optional: (--channel conda-forge)

  3. if you just want the main modules: conda install -c conda-forge opencv Any installation with pip did not work for me.

Upvotes: 0

BoKuan Liu
BoKuan Liu

Reputation: 41

The basic idea is deciding the scale changed every time on mouse wheel.

After you get the current scale (v.s. origin image) and correct region of image you want to show on screen, you can get the position and length of rectangle on scaled image.

So you can draw this rectangle on scaled image.

In my github,check how the class COpenCVWindowExt is implemented, more importantly, this project can zoom in/out and pan image only using opencv window.

Although it's c++ code, you only need to transform imshow () and resize () to python version.

Effect: enter image description here enter image description here

Part of the code:

void MouseCall (int event, int x, int y, int flag, void* pUserData)
{
    COpenCVWindowExt* pParent = (COpenCVWindowExt*)pUserData;
    if (event == EVENT_MOUSEWHEEL)
    {
        if (getMouseWheelDelta (flag) > 0 && pParent->m_iScaleTimes != pParent->m_iMaxScaleTimes)
            pParent->m_iScaleTimes++;
        else if (getMouseWheelDelta (flag) < 0 && pParent->m_iScaleTimes != pParent->m_iMinScaleTimes)
            pParent->m_iScaleTimes--;

        if (pParent->m_iScaleTimes == 0)
            pParent->m_dCompensationX = pParent->m_dCompensationY = 0;

        //Pixel value = mouse offset (v.s. window's left top position)
        //But using x, y is not correct in Wheel Event. So, use pre recorded value
        x = pParent->m_iMouseX;
        y = pParent->m_iMouseY;
        double dPixelX = (pParent->m_iHorzScrollBarPos + x + pParent->m_dCompensationX) / pParent->m_dNewScale;
        double dPixelY = (pParent->m_iVertScrollBarPos + y + pParent->m_dCompensationY) / pParent->m_dNewScale;

        pParent->m_dNewScale = pParent->m_dInitialScale * pow (pParent->m_dScaleRatio, pParent->m_iScaleTimes);

        if (pParent->m_iScaleTimes != 0)
        {
            int iWidth = pParent->m_matSrc.cols;
            int iHeight = pParent->m_matSrc.rows;

            pParent->m_iHorzScrollBarRange_Max = int (pParent->m_dNewScale * iWidth - pParent->m_dInitialScale * iWidth) - 1;
            pParent->m_iVertScrollBarRange_Max = int (pParent->m_dNewScale * iHeight - pParent->m_dInitialScale * iHeight) - 1;
            int iBarPosX = pParent->m_iHorzScrollBarPos = int (dPixelX * pParent->m_dNewScale - x + 0.5);
            int iBarPosY = pParent->m_iVertScrollBarPos = int (dPixelY * pParent->m_dNewScale - y + 0.5);
            pParent->m_dCompensationX = -iBarPosX + (dPixelX * pParent->m_dNewScale - x);
            pParent->m_dCompensationY = -iBarPosY + (dPixelY * pParent->m_dNewScale - y);
        }
        else
        {
            pParent->m_iHorzScrollBarPos = 0;
            pParent->m_iVertScrollBarPos = 0;
        }
        pParent->RefreshImage ();
    }
    else if (event == EVENT_MOUSEMOVE)
    {
        pParent->m_iMouseX = x;
        pParent->m_iMouseY = y;

    }
}

Upvotes: 2

kyshel
kyshel

Reputation: 592

A detour, by PIL:

import cv2
from PIL import Image

img = cv2.imread('lena.jpg')
img2 = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
im_pil = Image.fromarray(img2)
im_pil.show()

Upvotes: 4

mluerig
mluerig

Reputation: 749

see https://gist.github.com/BartG95/1ce8ba1e9c25ec3698d1

appears to be a longer procedure though, so you could instead switch to matplotlib's pyplot function (uses Qt). you need to apply this oneliner before (see Extracting a region from an image using slicing in Python, OpenCV for details):

import cv2
import matplotlib.pyplot as plt

image = cv2.imread("~\\imagedir\\image.jpg")
plt_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
imgplot = plt.imshow(plt_image)

Upvotes: 6

Related Questions