Issue about loading bitmaps in CTreeCtrl - mfc

I am trying to create an image list to my control, and load additional images. The problem is that only the image that i create is used and the loaded images does not displayed. Here is my ccode:
define IMAGE1 1
define IMAGE2 2
define IMAGE3 3
define IMAGE4 4
define IMAGE5 5
m_Bitmap1.LoadBitmap(IDB_BITMAP1);
m_Bitmap2.LoadBitmap(IDB_BITMAP2);
m_Bitmap3.LoadBitmap(IDB_BITMAP3);
m_ImageListTree = new CImageList;
m_ImageListTree->Create(IDB_BITMAP1, 16, 1, RGB(255, 255, 255));
m_ImageListTree->Add(&m_Bitmap2, RGB(255, 255, 255));
m_ImageListTree->Add(&m_Bitmap3, RGB(255, 255, 255));
while( ItemTree != NULL)
{
BasicTree->SetItemImage(ItemTree, nCounter, nCounter);
ItemTree = BasicTree->GetNextItem(ItemTree, TVGN_CHILD);
nCounter++;
}
The only IDB_BITMAP1 is displayed in all tree levels. Any ideas?

Actually I was never in the loop, as i did not get the initial HTRREITEM before entering the loop.
Also the creation of the list in the control, intialises every new item with the bitmap you are using for the creation. You can set the image eitehr in insertion or in alter though you need to specify diferent image (fo insertion you need to define a TVINSERTSTRUCTW and set the image before inserting the whole item.

Related

C++. OpenCV. Count number of conturs

I need get number of contours (only closed/looped contours) from my image. For this purpose I use cv::connectedComponents function. As it said in documentation
returns N, the total number of labels [0, N-1] where 0 represents the background label
So to get real nubmer of counturs I just need decrement returned value (sub background contour). This method works fine for most images I need to process (actually, it autocad files). However, I've got one image which is processed incorrectly. Returned value for this image 4, however we see that there are 4 circles on image and background. So returned value should be 5.
Here is image I got the problem with:
Here is the code I use:
void run_test()
{
cv::Mat img, img_edge, labels;
img = cv::imread("G:\\test.jpg", cv::IMREAD_GRAYSCALE);
cv::threshold(img, img_edge, 128, 255, cv::THRESH_BINARY);
int res = cv::connectedComponents(img_edge, labels, 8, CV_16U);
}
So I've got two questions: why returned value for this image is 4(but not 5) and is it correct way (by using connectedComponents) to get number of contours?

Copy image to section of another image

I am attempting to copy an image to another image (place a logo in the bottom right side of an image). My code successfully copies the logo onto the room image but it does some weird stretching when I apply a mask.
// Overlay logo
// src = 3 channel image of a room
// logo = 3 channel image of a logo (most of the Mat is black except for the logo).
// logo is smaller than the room image
Mat res;
Mat thresh;
src.copyTo(res);
threshold(logo, thresh, 1, 255, CV_THRESH_BINARY);
Rect r(res.cols-logo.cols, res.rows-logo.rows, logo.cols, logo.rows);
logo.copyTo(res(r), thresh);
My result:
Mask is:
Your logo seems to be a color image. Which means that your thresh image is also a color image. When you use it as a mask, it's going to be horizontally stretched because the extra channels are interpreted as more columns.
Try adding cvtColor(logo, grayLogo, CV_BGR2GRAY) before the threshold and use the grayLogo in the threshold.
Mask size and image size are not equal (thats why mask is streched). To solve this, you should create mask image and copy your threshed logo in good position.
[EDIT]: According to sunreef's answer - three channels in mask could also be a source of your problem.
Code posted below worked for me.
cv::Mat t_roomImage = cv::imread("E:\\Workspace\\KS\\misc\\M4nKr.jpg");
cv::Mat t_logoImage = cv::imread("E:\\Workspace\\KS\\misc\\7sFbv.jpg",0);
cv::threshold(t_logoImage, t_logoImage, 10, 255, CV_THRESH_BINARY);
cv::Mat t_mask = cv::Mat::zeros(t_roomImage.size(), CV_8U);
cv::Rect t_rect = cv::Rect(t_mask.cols - t_logoImage.cols, t_mask.rows -
t_logoImage.rows, t_logoImage.cols, t_logoImage.rows);
t_logoImage.copyTo(t_mask(t_rect));
t_roomImage.setTo(cv::Scalar(255, 0, 0), t_mask);
I used setTo, because I had no logo image. There you can use copyTo instead.
Results:

OpenCV: Text does not display when using the Qt library with cvFontQt and cvAddText on Windows 10 in VS2015 x64 build

I am am trying to use OpenCV to create an image from text. The image may or may not have an overlay that needs to be merged with it. The font of the Text needs to be needs to be different than the HERSHEY text that comes with the C++ interface of OpenCV. I saw in this post and others that it can be done using the cvFontQt and cvAddText.
I am using OpenCV 2.4.13 and Qt 5.6. In the sample code below I can output the first and third lines using cvPutText with cvFont and HERSHEY however the second line using cvAddText with cvFontQt does not display.
#include "stdafx.h"
#include "opencv2\core\core_c.h"
#include "opencv2\highgui\highgui_c.h"
int main()
{
// Create a window for a container to hold the image
cvNamedWindow("cvtest", CV_WINDOW_AUTOSIZE);
IplImage *img = cvCreateImage(cvSize(600, 300), IPL_DEPTH_64F, 4);
// Set the image background to white
cvSet(img, cvScalar(255, 255, 255));
CvFont font;
cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, 0.5, 0.5);
cvPutText(img, "cvInitFont; cvPutText: First line.", cvPoint(4, 30), &font, cvScalar(255));
CvFont fontqt = cvFontQt("Courier New", -1, cvScalar(0,0,255), CV_FONT_NORMAL, CV_STYLE_NORMAL, 0);
cvAddText(img, "cvFontQV; cvAddText: Second line.", cvPoint(4, 60), &fontqt);
cvPutText(img, "cvInitFont; cvPutText: Third line.", cvPoint(4, 90), &font, cvScalar(255));
cvShowImage("cvtest", img);
cvWaitKey(0);
cvSaveImage("C:\\OpenCvTest64F.jpg", img);
// Cleanup
cvDestroyAllWindows();
cvReleaseImage(&img);
return 0;
}
The resulting image ("C:\OpenCvTest64F.jpg"):
Output Image
Am I using cvFontQt or cvAddText incorrectly? Any thoughts on why it does not show up in the image?
Any specific reason why you are using floating point images? If not, try adjusting the image initialization to:
IplImage *img = cvCreateImage(cvSize(600, 300), IPL_DEPTH_8U, 3);
The use of a 3-channel 8-bit image seems to fix the problem.
Just a note - when assigning color to floating point images the value should be in the range [0, 1], not [0, 255]. Also, the C++ api is much nicer!

Holding an image for runtime updating in OpenCV

I have an image I'd like to display using imshow() and to update at runtime: say I'd like to run a corner detection algorithm then display the corner on this same image - like in MATLAB figure plot(), hold plot() - the hold keyword hold the previous image/graph and enables a new plot on the same figure.
Is this possible to do with OpenCV? If yes, how can I do it?
thanks
In C++, you don't need to hold it in order to update drawing. You just need to draw what you want to the image and then imshow the image. There you go.
Look at the following example from here:
int Displaying_Big_End( Mat image, char* window_name, RNG rng )
{
Size textsize = getTextSize("OpenCV forever!", CV_FONT_HERSHEY_COMPLEX, 3, 5, 0);
Point org((window_width - textsize.width)/2, (window_height - textsize.height)/2);
int lineType = 8;
Mat image2;
for( int i = 0; i < 255; i += 2 )
{
image2 = image - Scalar::all(i);
putText( image2, "OpenCV forever!", org, CV_FONT_HERSHEY_COMPLEX, 3,
Scalar(i, i, 255), 5, lineType );
imshow( window_name, image2 );
if( waitKey(DELAY) >= 0 )
{ return -1; }
}
return 0;
}
Pay attention to the imshow( window_name, image2 ), we don't do anything to hold the image, just use the loop to draw incrementally (by putText()) on the image. The image will update dynamically accordingly.
There is no concept of hold in OpenCV.
Basically, cv::imshow() will just update the window with whatever image it gets.
To "overlay" you actually need to create a new image (or reuse an existing one), draw on this new image and/or update it, e.g. with your detected corners, and call imshow() again with this updated image.

How to set ROI in OpenCV?

I have two images, the first one smaller than the other. I need to copy the second image on the first image. To do so, I need to set the ROI on the first one, copy the second image onto the first one and then reset the ROI.
However I am using the C++ interface so I have no idea how to do this. In C I could have used cvSetImageROI but this doesn't work on the C++ interface.
So basically whats the C++ alternative to cvSetImageROI?
//output is a pointer to the mat whom I want the second image (colourMiniBinMask) copied upon
Rect ROI (478, 359, 160, 120);
Mat imageROI (*output, ROI);
colourMiniBinMask.copyTo (imageROI);
imshow ("Gravity", *output);
I think you have something wrong. If the first one is smaller than the other one and you want to copy the second image in the first one, you don't need an ROI. You can just resize the second image in copy it into the first one.
However if you want to copy the first one in the second one, I think this code should work:
cv::Rect roi = cv::Rect((img2.cols - img1.cols)/2,(img2.rows - img1.rows)/2,img1.cols,img1.rows);
cv::Mat roiImg;
roiImg = img2(roi);
img1.copyTo(roiImg);
This is the code I used. I think the comments explain it.
/* ROI by creating mask for the parallelogram */
Mat mask = cvCreateMat(480, 640, CV_8UC1);
// Create black image with the same size as the original
for(int i=0; i<mask.cols; i++)
for(int j=0; j<mask.rows; j++)
mask.at<uchar>(Point(i,j)) = 0;
// Create Polygon from vertices
vector<Point> approxedRectangle;
approxPolyDP(rectangleVertices, approxedRectangle, 1.0, true);
// Fill polygon white
fillConvexPoly(mask, &approxedRectangle[0], approxedRectangle.size(), 255, 8, 0);
// Create new image for result storage
Mat imageDest = cvCreateMat(480, 640, CV_8UC3);
// Cut out ROI and store it in imageDest
image->copyTo(imageDest, mask);
I also wrote about this and put some pictures here.