how to resize the image through imshow (opencv , imshow )? - c++

I am trying to show an image. but imshow shows the image with big scales so that I can see the image's pixels(as shown in the image below)
as you see pixels are too big. and it is not nice. I expected something like this:
is there any way to resize the image's window size?
I am using Linux vscode
here is my code:
int main()
{
Mat O_image = imread("lena.jpg");
namedWindow("hamid", CV_WINDOW_KEEPRATIO);
imshow("hamid", O_image);
waitKey(0);
return 0;
}
the pointer changes when I move the mouse to the edges but I can't resize it.

You can use a cv::namedWindow with WindowFlags to control the size of the output window.
cv::Mat img;
img = cv::imread("Lena.jpg", CV_LOAD_IMAGE_GRAYSCALE);
cv::namedWindow("A image of Lena", CV_WINDOW_NORMAL); //CV_WINDOW_NORMAL to enable the user to resize the window
cv::imshow("A image of Lena", img);

Related

Having issues resizing an image with OpenCV

I want to resize an image to a specific size, it gets resized but cropped as well. What am I doing wrong?
my code:
cv::Mat Processor::process_image(cv::Mat& message)
{
float scale_down = 0.5;
cv::Mat resized_message;
cv::resize(message, resized_message, cv::Size(), scale_down, scale_down);
return resized_message;
}
int main()
{
cv::namedWindow("view", cv::WINDOW_AUTOSIZE);
...
resized_image = process_image(image);
cv::imshow("view", resized_image);
cv::waitKey(30);
}
This one is my source image:
This is what I get:
It seems that the mono8 in my publish function produces the error.
img_publisher.publish(cv_bridge::CvImage(std_msgs::Header(), "mono8", message_to_publish.get_image()).toImageMsg());
because if I publish the image as bgr8 it works fine.
img_publisher.publish(cv_bridge::CvImage(std_msgs::Header(), "bgr8", message_to_publish.get_image()).toImageMsg());
So I need to convert the image to grayscale after resizing.

Opencv c++ resize function: new Width should be multiplied by 3

I am programming in Qt environment and I have a Mat image with size 2592x2048 and I want to resize it to the size of a "label" that I have. But when I want to show the image, I have to multiply the width by 3, so the image is shown in its correct size. Is there any explanation for that?
This is my code:
//Here I get image from the a buffer and save it into a Mat image.
//img_width is 2592 and img_height is 2048
Mat image = Mat(cv::Size(img_width, img_height), CV_8UC3, (uchar*)img, Mat::AUTO_STEP);
Mat cimg;
double r; int n_width, n_height;
//Get the width of label (lbl) into which I want to show the image
n_width = ui->lbl->width();
r = (double)(n_width)/img_width;
n_height = r*(img_height);
cv::resize(image, cimg, Size(n_width*3, n_height), INTER_AREA);
Thanks.
The resize function works well, because if you save the resized image as a file is displayed correctly. Since you want to display it on QLabel, I assume you have to transform your image to QImage first and then to QPixmap. I believe the problem lies either in the step or the image format.
If we ensure the image data passed in
Mat image = Mat(cv::Size(img_width, img_height), CV_8UC3, (uchar*)img, Mat::AUTO_STEP);
are indeed an RGB image, then below code should work:
ui->lbl->setPixmap(QPixmap::fromImage(QImage(cimg.data, cimg.cols, cimg.rows, *cimg.step.p, QImage::Format_RGB888 )));
Finally, instead of using OpenCV, you could construct a QImage object using the constructor
QImage((uchar*)img, img_width, img_height, QImage::Format_RGB888)
and then use the scaledToWidth method to do the resize. (beware thought that this method returns the scaled image, and does not performs the resize operation to the image per se)

image window not responding opencv during program running

I am running a code something like that;
Mat img1 = imread("C:\\input0.png");
namedWindow("original");
imshow("original", img1 );
int lowThreshold = 20;
int ratio = 2;
int kernel_size = 5;
Mat edge_map;
Mat gray_image;
cvtColor(img1, gray_image, CV_BGR2GRAY);
Canny(gray_image, edge_map, lowThreshold, lowThreshold*ratio, kernel_size);
namedWindow("Edge Image");
imshow("Edge Image", edge_map);
Mat result_image = produce_the_result_image(img1, edge_map);
namedWindow("Final Image");
imshow("Final Image", result_image );
int key = 1;
while (key != 'q') {
key = waitKey(5);
}
Till shows the last image (Final Image window), other windows show 'not responding', however, after the last function finishes (produce_the_result_image), which lasts 2-3 minutos and shows the all image windows, the error disappears. Is that normal?
Thanks!
Images in OpenCV will not display or respond until you have called waitKey();. So if after your first two calls to imshow you call waitKey(1);, the image will display (it will wait one millisecond for a key press and then it will become nonresponsive). If you call waitKey(); with no arguments or use a while loop similar to the one at the end of the code, the images will display and respond. Once you press a key, the images will become nonresponsive again.
So yes, this is normal behavior for OpenCV. Note that it applies to all windows at once: either they are all responsive, if waitKey is currently being called, or none of them are responsive.

GrabCut reading mask from PNG file in OpenCV (C++)

The implementation of this functionality seems pretty straightforward in Python, as shown here: http://docs.opencv.org/trunk/doc/py_tutorials/py_imgproc/py_grabcut/py_grabcut.html
Yet, when I tried to do exactly the same in C++, I get bad arguments error (for the grabcut function). How to put the mask image in the right format?
I am a newbie at this, so I'd be very thankful if someone could help me understand better. Thank you!
Here's what I have so far:
Mat image;
image= imread(file);
Mat mask;
mask.setTo( GC_BGD );
mask = imread("messi5.png");
Mat image2 = image.clone();
// define bounding rectangle
cv::Rect rectangle(startX, startY, width, height);
cv::Mat result; // segmentation result (4 possible values)
cv::Mat bgModel,fgModel; // the models (internally used)
//// GrabCut segmentation that works, but with a rectangle, not with the mask I need
//cv::grabCut(image, // input image
// result, // segmentation result
// rectangle,// rectangle containing foreground
// bgModel,fgModel, // models
// 1, // number of iterations
// cv::GC_INIT_WITH_RECT); // use rectangle
grabCut( image, mask, rectangle, bgModel, fgModel, 1, GC_INIT_WITH_MASK);
cv::compare(mask,cv::GC_PR_FGD,mask,cv::CMP_EQ);
cv::Mat foreground(image.size(),CV_8UC3,cv::Scalar(255,255,255));
image.copyTo(foreground,mask); // bg pixels not copied
namedWindow( "Display window", WINDOW_AUTOSIZE );
imshow( "Display window", foreground );
waitKey(0);
return 0;
}
It looks like you have misunderstood the guide, repeated here from the linked guide in the question:
# newmask is the mask image I manually labelled
newmask = cv2.imread('newmask.png',0)
# whereever it is marked white (sure foreground), change mask=1
# whereever it is marked black (sure background), change mask=0
mask[newmask == 0] = 0
mask[newmask == 255] = 1
mask, bgdModel, fgdModel = cv2.grabCut(img,mask,None,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_MASK)
mask = np.where((mask==2)|(mask==0),0,1).astype('uint8')
img = img*mask[:,:,np.newaxis]
plt.imshow(img),plt.colorbar(),plt.show()
this is not what you have done i'm afraid. For a start you seem to have set the mask to the rgb image:
mask = imread("messi5.png");
whereas is should be set to the mask image:
mask = imread("newmask.png",CV_LOAD_IMAGE_GRAYSCALE);
EDIT from comments:
from a pure red mask painted over the image (an actual mask would be better).
maskTmp = imread("messi5.png");
std::vector<cv::Mat> channels(3)
split( messi5, channels);
cv::Mat maskRed = channels[2];
now threshold on the red channel to get your binary mask.

OpenCV - How to enable scrolling to windows with images?

So currently I open images created with openCV with something like
cvNamedWindow( "Original Image", CV_WINDOW_AUTOSIZE );
cvShowImage( "Original Image", original );
but my images are quite large and go off the screen like shown here
I want windows to be resizable or at least the size of the users screen but with scrolling.
How to do such thing?
A simple way to scroll large image is by usage of trackbar and a Rectangular for snipping.
.
.
.
namedWindow("winImage",WINDOW_AUTOSIZE);
namedWindow("controlWin",WINDOW_AUTOSIZE);
int winH=300;
int winW=600;
if(winH>=largeImage.rows)winH=largeImage.rows-1;
if(winW>=largeImage.cols)winW=largeImage.cols-1;
int scrolHight=0;
int scrolWidth=0;
cvCreateTrackbar("Hscroll", "controlWin", &scrolHight, (largeImage.rows -winH));
cvCreateTrackbar("Wscroll", "controlWin", &scrolWidth, (largeImage.cols -winW));
while(waitKey(0)!='q'){
Mat winImage= largeImage( Rect(scrolWidth,scrolHight,winW,winH) );
imshow("winImage",winImage);
}//while
.
.
EDIT
Short answer: you can't "enable" it, you have to implement it.
OpenCV does have trackbars -- have a look at the documentation, in particular the cvCreateTrackbar function. However, even if you use them, you still have to write the code behind it (for determining the new ROI and determining what to actually show).
If this sounds a bit too daunting, then you can wrap the displayed image using some GUI framework. Here is an example that uses OpenCV with wxWidgets. Of course, you can use any other GUI framework (for example, Qt).
This might help for one step: Just use CV_WINDOW_NORMAL instead of CV_WINDOW_AUTOSIZE.
cvNamedWindow(yourWindowName, CV_WINDOW_NORMAL);
cvShowImage("Original Image", original);
As far as I know (but I've only recently started looking at OpenCV) you need to build the OpenCV library with the Qt GUI library as GUI backend.
Then you get all the cute functions.
Well, OK, there's not very much, but the little that is there is documented as Qt only.
EDIT: PS, since possibly other answer might sow confusion, I'm not talking about using Qt to implement such functionality yourself. I'm talking about the functionality available in OpenCV's HighGUI module.
Cheers & hth.,
The best thing that I can do with pure opencv is by modifying the opencv trackbar method. I'm using ROI to update the display image according to the slider value. The weakness of this method is, opencv trackbar is displayed horizontally not vertically like the normal scrollbar, so in this case it is up to you whether you want to rotate your image horizontally or not.
int slider_max, slider, displayHeight;
int displayWidth = 1900;
Mat src1; // original big image
Mat dst;
cv::Rect roi;
static void on_trackbar(int, void*)
{
roi = cv::Rect(slider, 0, displayWidth, displayHeight); //Update ROI for display
dst = src1(roi);
imshow("Result", dst);
}
int main(void)
{
src1 = imread("BigImg.jpg"); // your big image
cv::rotate(src1, src1, cv::ROTATE_90_CLOCKWISE); //I rotate my image because opencv trackbar is displayed horizontally
cv::resize(src1, src1, cv::Size(src1.cols/2, src1.rows/2)); // resize the image if it's too big to display in 1 window
if (src1.empty()) { cout << "Error loading src1 \n"; return -1; }
slider_max = src1.cols - displayWidth;
slider = 0;
displayHeight = src1.rows;
namedWindow("Result", WINDOW_AUTOSIZE); // Create Window
char TrackbarName[50];
sprintf(TrackbarName, "Pixel Pos");
createTrackbar(TrackbarName, "Result", &slider, slider_max, on_trackbar);
on_trackbar(slider, 0);
waitKey(0);
return 0;
}
For changing the trackbar's orientation then you will need to use Qt or other GUI How to change the position of the trackbar in OpenCV applications?