Skip to content

Commit

Permalink
fix(tracking): don't translate width/height
Browse files Browse the repository at this point in the history
Camera resolution does not match the dimensions of the rendered
component. So when a QR code is detected we need to adjust it's
coordinates before it's passed to the track function. For that
xy-coordinates need to be scaled to account for responsiveness and
they need to be translated to account for cropping (especially in
fullscreen mode).

However, widths/heights don't need to be translated since they only have
magnitude but no position. That error caused tracking to messed up in
fullscreen mode for tracking functions that use width/height in the
boundingBox property.

Issue: #244
  • Loading branch information
gruhn committed May 26, 2021
1 parent 094fd2f commit f2fcf92
Showing 1 changed file with 41 additions and 34 deletions.
75 changes: 41 additions & 34 deletions src/components/QrcodeStream.vue
Original file line number Diff line number Diff line change
Expand Up @@ -200,55 +200,62 @@ export default {
if (canvas !== undefined) {
if (detectedCodes.length > 0 && this.track !== undefined && video !== undefined) {
// The visually occupied area of the video element.
// Because the component is responsive and fills the available space,
// this can be more or less than the actual resolution of the camera.
const displayWidth = video.offsetWidth;
const displayHeight = video.offsetHeight;
// The actual resolution of the camera.
// These values are fixed no matter the screen size.
const resolutionWidth = video.videoWidth;
const resolutionHeight = video.videoHeight;
// Dimensions of the video element as if there would be no
// object-fit: cover;
// Thus, the ratio is the same as the cameras resolution but it's
// scaled down to the size of the visually occupied area.
const largerRatio = Math.max(
displayWidth / resolutionWidth,
displayHeight / resolutionHeight
);
const uncutWidth = resolutionWidth * largerRatio;
const uncutHeight = resolutionHeight * largerRatio;
const xScalar = uncutWidth / resolutionWidth;
const yScalar = uncutHeight / resolutionHeight;
const xOffset = (displayWidth - uncutWidth) / 2;
const yOffset = (displayHeight - uncutHeight) / 2;
const scale = ({ x, y }) => {
return {
x: Math.floor(x * xScalar),
y: Math.floor(y * yScalar)
};
}
const adjustPoint = ({ x, y }) => {
// The visually occupied area of the video element.
// Because the component is responsive and fills the available space,
// this can be more or less than the actual resolution of the camera.
const displayWidth = video.offsetWidth;
const displayHeight = video.offsetHeight;
// The actual resolution of the camera.
// These values are fixed no matter the screen size.
const resolutionWidth = video.videoWidth;
const resolutionHeight = video.videoHeight;
// Dimensions of the video element as if there would be no
// object-fit: cover;
// Thus, the ratio is the same as the cameras resolution but it's
// scaled down to the size of the visually occupied area.
const largerRatio = Math.max(
displayWidth / resolutionWidth,
displayHeight / resolutionHeight
);
const uncutWidth = resolutionWidth * largerRatio;
const uncutHeight = resolutionHeight * largerRatio;
const xScalar = uncutWidth / resolutionWidth;
const yScalar = uncutHeight / resolutionHeight;
const xOffset = (displayWidth - uncutWidth) / 2;
const yOffset = (displayHeight - uncutHeight) / 2;
const translate = ({ x, y }) => {
return {
x: Math.floor(x * xScalar + xOffset),
y: Math.floor(y * yScalar + yOffset)
x: Math.floor(x + xOffset),
y: Math.floor(y + yOffset)
};
}
const adjustedCodes = detectedCodes.map(detectedCode => {
const { boundingBox, cornerPoints } = detectedCode
const { x, y } = adjustPoint({
const { x, y } = translate(scale({
x: boundingBox.x,
y: boundingBox.y
})
const { x: width, y: height } = adjustPoint({
}))
const { x: width, y: height } = scale({
x: boundingBox.width,
y: boundingBox.height
})
return {
...detectedCode,
cornerPoints: cornerPoints.map(adjustPoint),
cornerPoints: cornerPoints.map(point => translate(scale(point))),
boundingBox: DOMRectReadOnly.fromRect({ x, y, width, height })
}
})
Expand Down

0 comments on commit f2fcf92

Please sign in to comment.