Image cropping for non standard aspect ratio format - c++

I am facing the problem of rendering the correct image with some portion of the edges cropped out. I can observe this only for non-standard aspect ratio.
In my case width is 1228 and height is 972 which is yielding an aspect ratio of 1.26.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glClearColor(0.0, 0.0, 0.0, 1.0);
float vx = float(m_uiImageWidth) / float(m_uiImageWidth);
float vy = float(m_uiImageHeight) / float(m_uiImageWidth);
glEnable(GL_TEXTURE_2D);
glTexImage2D(GL_TEXTURE_2D, 0, 3, m_uiImageWidth, m_uiImageHeight, 0, GL_BGR, GL_UNSIGNED_BYTE, m_arrayBufferVS1);
glLoadIdentity();
glBindTexture(GL_TEXTURE_2D, m_texture);
//glTranslatef(0.0f, 0.0f, -1.36f);
glTranslatef(0.0f, 0.0f, -1.358f);
//Normal
if(m_bContextMenuNormal)
glRotatef(180, 1, 0, 0);
else if (m_bContextMenuRotate180 && m_bContextMenuMirror)
{
//do nothing
}
else if(m_bContextMenuMirror)
glRotatef(180, 0, 0, 0);
else if(m_bContextMenuRotate180)
glRotatef(180, 0, 1, 0);
glScalef(1, -1, 1);
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 1.0f); //top right
glVertex3f(vx, vy, 0.0f);
glTexCoord2f(0.0f, 1.0f); // left top
glVertex3f(-vx, vy, 0.0f);
glTexCoord2f(0.0f, 0.0f); //left bottom
glVertex3f(-vx, -vy, 0.0f);
glTexCoord2f(1.0f, 0.0f); //right bottom
glVertex3f(vx, -vy, 0.0f);
glEnd();
glDisable(GL_TEXTURE_2D);
This is my code snippet. It would be a great help if anyone points out the mistake I have made and suggestions to fix.

modify your calls to glTexCoord2f, the decimal values are interpolated between the four vertexes and then multiplied by the width and height of the image to calculate the coordinates of each pixel from the texture to draw to the screen. if you want to crop the left and right of your image with an aspect ratio of 1.26 into a square you would use the following texture coordinates:
glTexCoord2f(1.0f - 0.13f, 1.0f); //top right
glTexCoord2f(0.0f + 0.13f, 1.0f); // left top
glTexCoord2f(0.0f + 0.13f, 0.0f); //left bottom
glTexCoord2f(1.0f - 0.13f, 0.0f); //right bottom
0.13 * 1228 is 159.64 pixels, and when you remove 159.64 pixels from either side of your 1228 pixel wide texture the remaining portion of the image is 972 pixels wide, meaning the aspect ratio of the pixels drawn will be 1:1 because your texture is 972 pixels tall

Related

How do I change the viewing angle in OpenGL?

I need to create a 3d cube, and so far I've created all the vertices but when I run the program I can only see the cube (or what I hope is a cube, I can't tell) from one face, so it looks like a square. I want to know how to view my cube from above, so I can check whether or not it actually looks the way I want it to.
I created the 24 vertices using glVertex3f but like I said I can't tell if it is a cube or not because I cannot look at it from an angle other than the default.
I tried downloading GLM but I am very confused on how, if at all, to use that to change the viewing perspective.
glEnable(GL_DEPTH_TEST);
// Loop until the user closes the window
while (!glfwWindowShouldClose(window))
{
// Render here
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_QUADS);
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3f(0.5f, 0.5f, 0.5f);
glVertex3f(-0.5f, 0.5f, 0.5f);
glVertex3f(-0.5f, -0.5f, 0.5f);
glVertex3f(0.5f, -0.5f, 0.5f);
... // Repeating drawing the vertices for each vertex of the cube
glEnd();
// Swap front and back buffers
glfwSwapBuffers(window);
// Poll for and process events
glfwPollEvents();
}
No error messages but I cant tell if its a cube or not.
// Render here
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// need the window width & height to compute aspect ratio
int width, height;
glfwGetWindowSize(window, &width, &height);
// set up the camera projection (if you haven't done this in init)
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, float(width) / height, 0.1f, 100.0f);
// set camera position & orientation
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(1, 1, -3, //< eye position
0, 0, 0, //< aim position
0, 1, 0); //< up direction
// now draw stuff
glBegin(GL_QUADS);
glEnd();

Get ScreenCoordinates from 3D object OpenGL and draw sample points

I am working on a Particle Filter that needs to compare coordinates of pixels detected from a VideoCapture with coordinates of sample points on a 3D object. Currently, there are no sample points, but just one (top left corner of the cube you see on the (left) image below). However, contours are detected and drawn (there are not many as it's dark, but please ignore that for now) on the video stream, which means I can easily get their [x,y] coordinates.
The problem here was that I could not (properly) translate 3D coordinates of the object into 2D screen coordinates. I am using perspective projection as I obviously draw 3D objects.
Left - Video Capture / Right - coordinates(first comes the "translated" screen followed by object coordinates relative to origin point (0,0) in the centre, and then normalized errors, which represent the error in distance from the origin point (ignore that for now)):
The problem was that for each particle I was getting projection and model view matrices over and over. I simply moved the code for obtaining matrices before the for loop in order to get them only once. It worked!!!
Here is the initialisation of the screen and vectors that I am using:
int width = 640;
int height = 480;
Mat image;
int iteration = 0;
struct Coordinates{ //stores coordinates of drawn particles
GLdouble x;
GLdouble y;
GLdouble z;
GLdouble angle;
};
struct ScreenCoordinates{ //stores coordinates on screen
GLdouble x;
GLdouble y;
GLdouble z;
};
float X_object, Y_object, Z_object, cube_angle;
GLdouble sum_of_errors;
GLint viewport[4];
GLdouble mvmatrix[16], projmatrix[16];
vector<Coordinates> points(number_of_particles);
vector<GLdouble> errors(number_of_particles);
vector<GLdouble> normalizedErrors(number_of_particles);
vector<GLint> indexes(number_of_particles);
vector<GLdouble> weights(number_of_particles);
vector<vector<Point>> Contours;// = new vector<vector<Point>>(number_of_particles); //2D vector for storing the edges coordinates
vector<Point> screenCoordinates;
vector<ScreenCoordinates> point_on_screen(number_of_particles);
Particles are drawn in the following way:
void drawParticle()
{
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear color and depth buffers
glPushAttrib(GL_POLYGON_BIT | GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT) ;
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) ;
//glDisable(GL_LIGHTING) ;
glBegin(GL_QUADS); // Begin drawing the color cube with size 3cm x 3.5cm x 4cm
// Top face (y = 1.0f)
// Define vertices in counter-clockwise (CCW) order with normal pointing out
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f( 1.75f, 1.75f, -4.0f);
glVertex3f(-1.75f, 1.75f, -4.0f);
glVertex3f(-1.75f, 1.75f, 1.0f);
glVertex3f( 1.75f, 1.75f, 1.0f);
// Bottom face (y = -1.0f)
glColor3f(1.0f, 0.5f, 0.0f); // Orange
glVertex3f( 1.75f, -1.75f, 1.0f);
glVertex3f(-1.75f, -1.75f, 1.0f);
glVertex3f(-1.75f, -1.75f, -4.0f);
glVertex3f( 1.75f, -1.75f, -4.0f);
// Front face (z = 1.0f)
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f( 1.75f, 1.75f, 1.0f);
glVertex3f(-1.75f, 1.75f, 1.0f);
glVertex3f(-1.75f, -1.75f, 1.0f);
glVertex3f( 1.75f, -1.75f, 1.0f);
// Back face (z = -1.0f)
glColor3f(1.0f, 1.0f, 0.0f); // Yellow
glVertex3f( 1.75f, -1.75f, -4.0f);
glVertex3f(-1.75f, -1.75f, -4.0f);
glVertex3f(-1.75f, 1.75f, -4.0f);
glVertex3f( 1.75f, 1.75f, -4.0f);
// Left face (x = -1.0f)
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(-1.75f, 1.75f, 1.0f);
glVertex3f(-1.75f, 1.75f, -4.0f);
glVertex3f(-1.75f, -1.75f, -4.0f);
glVertex3f(-1.75f, -1.75f, 1.0f);
// Right face (x = 1.0f)
glColor3f(1.0f, 0.0f, 1.0f); // Magenta
glVertex3f(1.75f, 1.75f, -4.0f);
glVertex3f(1.75f, 1.75f, 1.0f);
glVertex3f(1.75f, -1.75f, 1.0f);
glVertex3f(1.75f, -1.75f, -4.0f);
glEnd(); // End of drawing color-cube
glPopAttrib() ;
}
Display function:
void display()
{
// clear the window
glClear( GL_COLOR_BUFFER_BIT );
// show the current camera frame
//based on the way cv::Mat stores data, you need to flip it before displaying it
cv::Mat tempimage;
cv::flip(image, tempimage, 0);
glDrawPixels( tempimage.size().width, tempimage.size().height, GL_RGB, GL_UNSIGNED_BYTE, tempimage.ptr() );
//////////////////////////////////////////////////////////////////////////////////
// Here, set up new parameters to render a scene viewed from the camera.
//set viewport
glViewport(0, 0, tempimage.size().width, tempimage.size().height);
//set projection matrix using intrinsic camera params
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
float aspect = tempimage.size().width*1.0/tempimage.size().height;
//gluPerspective is arbitrarily set, you will have to determine these values based
//on the intrinsic camera parameters
gluPerspective(60.0f, aspect, 0.1f, 100.0f);
//you will have to set modelview matrix using extrinsic camera params
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, 0, 5, 0, 0, 0, 0, 1, 0);
glGetIntegerv (GL_VIEWPORT, viewport);
glGetDoublev (GL_MODELVIEW_MATRIX, mvmatrix);
glGetDoublev (GL_PROJECTION_MATRIX, projmatrix);
/////////////////////////////////////////////////////////////////////////////////
// Drawing routine
//initialise certain number of particles
for(int i = 0; i<number_of_particles; i++){
// uniformly distributed for the very first generation
if((points[i].x == NULL) || (points[i].y = NULL)){
//randomly generate X,Y,Z and angle values
X_object = RandomNumber(-5.0, 5.0);//rand() % 10 - 2.5;
Y_object = RandomNumber(-5.0, 5.0);//rand() % 10 - 2.5;
Z_object = 23;
cube_angle = rand() % 360 + 1;
}else{
//printf("second generation should improve the distribution");
//set sigma accordingly
//use best particle coordinates for the next X and Y
X_object = points[i].x;
Y_object = points[i].y;
Z_object = points[i].z;
cube_angle = points[i].angle;
}
points[i].x = X_object;
points[i].y = Y_object;
points[i].z = Z_object;
points[i].angle = cube_angle;
gluProject(X_object, Y_object, Z_object, mvmatrix, projmatrix, viewport, &point_on_screen[i].x, &point_on_screen[i].y, &point_on_screen[i].z);
printf("Screen: %f, %f\n", point_on_screen[i].x, point_on_screen[i].y);
//now that the camera params have been set, draw your 3D shapes
//first, save the current matrix
//glPushMatrix();
//move to the position where you want the 3D object to go
glLoadIdentity();
glTranslatef(X_object, Y_object, -Z_object); //this is an arbitrary position for demonstration
glRotatef(cube_angle, 1.0f, 1.0f, 1.0f); // Rotate about (1,1,1)-axis [NEW]
drawParticle();
//glPopMatrix();
}
scoreParticles();
// show the rendering on the screen
glutSwapBuffers();
// post the next redisplay
glutPostRedisplay();
}
This is the exact way of translation:
glGetIntegerv (GL_VIEWPORT, viewport);
glGetDoublev (GL_MODELVIEW_MATRIX, mvmatrix);
glGetDoublev (GL_PROJECTION_MATRIX, projmatrix);
gluProject(X_object, Y_object, Z_object, mvmatrix, projmatrix, viewport, &point_on_screen[i].x, &point_on_screen[i].y, &point_on_screen[i].z);
printf("Screen: %f, %f\n", point_on_screen[i].x, point_on_screen[i].y);
The question now is how can I include sample points between vertices? Taking into account the way I draw particles, how should I divide the space between all vertices into equal parts and place a point there so that this point can be translated into screen coordinates and then compared to pixel coordinates?
Just for clarification: the error in distance for each particle is found and a certain weight is assigned, after that I use Stochastic Sampling for redistribution of particles over following population.

Text color is not correct

void text(string str)
{
for (int i = 0; i < str.length(); i++)
{
glColor3f(0.0f, 0.0f, 0.0f);
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, str[i]);
}
}
void render(void)
{
int width = glutGet(GLUT_WINDOW_WIDTH);
int height = glutGet(GLUT_WINDOW_HEIGHT);
if (height == 0) height = 1;
GLfloat aspect = (GLfloat)width / (GLfloat)height;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_SCISSOR_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, aspect, 0.1f, 100.0f);
// Top view - top left
glViewport(0, 0, width/2, height/2);
glScissor(0, 0, width/2, height/2);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
PilotView(0.0f, 0.0f, -5.0f, 0.0f, 0.0f, 0.0f, 1.0f);
glRasterPos3f(-0.1f, -0.1f, 4.0f);
text("Front");
diode();
// Corner view - top right
glViewport(width/2, 0, width/2, height/2);
glScissor(width/2, 0, width/2, height/2);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
PilotView(0.0f, 0.0f, -5.0f, 0.0f, -90.0f, 0.0f, 1.0f);
glRasterPos3f(4.0f, -0.1f, 0.1f);
text("Right");
diode();
// Front view - bottom left
glViewport(0, height/2, width/2, height/2);
glScissor(0, height/2, width/2, height/2);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
PilotView(0.0f, 0.0f, -5.0f, 90.0f, 0.0f, 0.0f, 1.0f);
glRasterPos3f(-0.1f, 4.0f, 0.0f);
text("Top");
diode();
// Right view - bottom right
glViewport(width/2, height/2, width/2, height/2);
glScissor(width/2, height/2, width/2, height/2);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
PilotView(0.0f, 0.0f, -5.0f, 20.0f, 0.0f, 0.0f, 1.0f);
glRasterPos3f(-0.1f, 4.0f, 0.0f);
text("Fro4nt");
diode();
glDisable(GL_SCISSOR_TEST);
glutSwapBuffers();
}
I'm not sure where the white "Front" and the yellow "Top"/"Right" is coming from (in terms of color). They all should be black. Does anyone know what the issue is?
Here is what the output looks like:
As suspected, this may come as a shock but glRasterPos (...) actually tracks the "current" color when you call that function. That is, whatever color was set before glRasterPos (...) was called, applies as the "current color" for drawing operations at that position. Think of it almost as the rasterizer's analog to glVertex (...), as I will explain below.
You need to set the current color before you call glRasterPos (...), to that end you should remove the glColor3f (...) call completely from your text (...) function, or perhaps modify that function to do both - set the color and then the raster pos, then draw the text.
glRasterPos — specify the raster position for pixel operations:
The current raster position consists of three window coordinates (x, y, z), a clip coordinate value (w), an eye coordinate distance, a valid bit, and associated color data and texture coordinates.

Texture coordinates don't correspond to cv::Mat Coordinates

What I want is to show a marker to the camera and, having found, overlay it with an image, for example this: (let's call image)
What I do is:
1) I open my webcam with opencv. I load image. I detect the marker in the captured frame. Calculating the coordinates of the marker with respect to frame.
#define WIDTH 600 //opengl window width
#define HEIGHT 440 //opengl window height
VideoCapture cap;
GLint window;
GLuint *textures = new GLuint[2];
vector <Point2f> coord(4);
int flag =0;
// Capture next frame
Mat frame;
cap >> frame;
flip(frame,frame,1);
aruco::CameraParameters CamParam;
aruco::MarkerDetector MDetector;
std::vector <Marker> Markers;
float MarkerSize=170;
//marker detection
CamParam.readFromXMLFile("parametri_camera.yml");
CamParam.resize( frame.size());
MDetector.detect(frame, Markers, CamParam, MarkerSize);
Mat image = imread("Immagine.png");
if (Markers.size()!=0) flag =1;
else flag =0;
for (int i=0; i< Markers.size(); i++) {
coord_marker(frame, Markers[i], CamParam, coord);
}
2) I transform/convert image and frame into two textures.
glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
glBindTexture(GL_TEXTURE_2D, textures[0]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, 4,frame.cols, frame.rows, 0, GL_RGB,GL_UNSIGNED_BYTE, frame.data);
glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glBindTexture(GL_TEXTURE_2D, textures[1]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, 4,image.cols, image.rows, 0, GL_RGB,GL_UNSIGNED_BYTE, image.data);
3) I show the two textures, where textures[1] is positioned in correspondence of the coordinates of the marker.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
// Set Projection Matrix
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, WIDTH, HEIGHT, 0);
// Switch to Model View Matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glBindTexture(GL_TEXTURE_2D, textures[0]);
// Draw a textured quad
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex2f(WIDTH, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex2f(WIDTH, HEIGHT);
glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, HEIGHT);
glEnd();
if(flag ==1) {
glBindTexture(GL_TEXTURE_2D, textures[1]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex2f((GLfloat)((coord[1].x)),(GLfloat)(coord[1].y));
glTexCoord2f(1.0f, 0.0f); glVertex2f((GLfloat)((coord[2].x)),(GLfloat)(coord[2].y));
glTexCoord2f(1.0f, 1.0f); glVertex2f((GLfloat)((coord[3].x)),(GLfloat)(coord[3].y));
glTexCoord2f(0.0f, 1.0f); glVertex2f((GLfloat)((coord[0].x)),(GLfloat)(coord[0].y));
glEnd();
}
glFlush();
glutSwapBuffers();
This is the result:
As you can see, textures[1] is shifted relative to the marker.
What am I missing? It looks like I need to do some transformation/conversion fom Mat coordinates to Texture coordinates. But how?
I found the error in my code.
Wrong to set the openGL window size (window size was smaller than captured frame). I had to size the window with the size of the captured frame (640x480). In this way, the coordinates of the marker in the Mat frame correspond to the coordinates of the marker in the textures[1].
#define WIDTH 640 //opengl window width and captured frame width
#define HEIGHT 480 //opengl window height and captured frame height
Hope this will help someone!

Blending problems (OpenGL)

A have a question, maybe someone can help me.
I am trying to make a mirror effect using OpenGL. I draw a transparent plane, a "reflected" scene cut by stencil, and an original one.
But I have a completely non-transparent "wall" instead of the mirror. I know it happens because of the first mirror plane rendering (to get a stencil buffer). But I don't know what to do with this:(
Here is the code:
void CMirror::draw(CSceneObject * curscene)
{
glPushMatrix();
glClearStencil(0.0f);
glClear(GL_STENCIL_BUFFER_BIT);
//Draw into the stencil buffer
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
glStencilFunc(GL_ALWAYS, 1, 0);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glEnable(GL_STENCIL_TEST);
glPushMatrix();
glTranslatef(this->coords[0], this->coords[1], this->coords[2]);
glScalef(this->size, this->size, this->size);
glColor4f(1, 0, 1, 0);
glBegin(GL_QUADS);
glVertex3f(0.0f, this->height / 2.0f, this->width / 2.0f);
glVertex3f(0.0f, this->height / -2.0f, this->width / 2.0f);
glVertex3f(0.0f, this->height / -2.0f, this->width / -2.0f);
glVertex3f(0.0f, this->height / 2.0f, this->width / -2.0f);
glEnd();
glPopMatrix();
glDisable(GL_STENCIL_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
//glClear(GL_COLOR_BUFFER_BIT);
//Draw the scene
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_EQUAL, 1, 255);
glPushMatrix();
glTranslatef( 2*this->coords[0], 2*this->coords[1], 2*this->coords[2]);
glScalef(-1.0f, 1.0f, 1.0f);
((CScene*)curscene)->draw();
glColor4f(0.0f, 0.30f, 0, 0.9);
((CScene*)curscene)->spline->draw();
((CScene*)curscene)->morph->draw();
glPopMatrix();
glDisable(GL_STENCIL_TEST);
//the mirror itself:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glPushMatrix();
glTranslatef(this->coords[0], this->coords[1], this->coords[2]);
glScalef(this->size, this->size, this->size);
glColor4f(0, 0, 0, 0.9);
glBegin(GL_QUADS);
glVertex3f(0.0f, this->height / 2.0f, this->width / 2.0f);
glVertex3f(0.0f, this->height / -2.0f, this->width / 2.0f);
glVertex3f(0.0f, this->height / -2.0f, this->width / -2.0f);
glVertex3f(0.0f, this->height / 2.0f, this->width / -2.0f);
glEnd();
glPopMatrix();
glDisable(GL_BLEND);
glPopMatrix();
}
What happens if you don't do that last draw (i.e. if the problem is still there, remove it as it complicates the example)?
One thing that's clear is that you don't seem to handle anything Z-buffer related.
When you draw your first quad to set the stencil, assuming Z-write is on, you end up setting the Z-values to your mirror Z. Drawing the scene that is supposed to be reflected in the mirror will be Z-rejected.
You need to clear the Z buffer for that region of the screen somehow. Obviously, a full Clear(DEPTH_BIT) can work but it depends on what you've already drawn on your screen.
Likewise, not updating the Z-buffer when updating the stencil can work depending on whether anything has been drawn there before.