Skip to content

Commit

Permalink
Merge pull request #8559 from cvat-ai/release-2.21.1
Browse files Browse the repository at this point in the history
Release v2.21.1
  • Loading branch information
cvat-bot[bot] authored Oct 18, 2024
2 parents 67d3645 + 8bc9f15 commit 4a7e8e0
Show file tree
Hide file tree
Showing 66 changed files with 541 additions and 237 deletions.
27 changes: 27 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,33 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

<!-- scriv-insert-here -->

<a id='changelog-2.21.1'></a>
## \[2.21.1\] - 2024-10-18

### Added

- Keyboard shortcuts for **brush**, **eraser**, **polygon** and **polygon remove** tools on masks drawing toolbox
(<https://github.com/cvat-ai/cvat/pull/8519>)

### Fixed

- Ground truth tracks are displayed not only on GT frames in review mode
(<https://github.com/cvat-ai/cvat/pull/8531>)

- Incorrect navigation by keyframes when annotation job ends earlier than track in a ground truth job
(<https://github.com/cvat-ai/cvat/pull/8533>)
- Tracks from a ground truth job displayed on wrong frames in review mode when frame step is not equal to 1
(<https://github.com/cvat-ai/cvat/pull/8533>)

- Task creation with cloud storage data and GT_POOL validation mode
(<https://github.com/cvat-ai/cvat/pull/8539>)

- Incorrect quality reports and immediate feedback with non default start frame or frame step
(<https://github.com/cvat-ai/cvat/pull/8551>)

- av context closing issue when using AUTO thread_type
(<https://github.com/cvat-ai/cvat/pull/8555>)

<a id='changelog-2.21.0'></a>
## \[2.21.0\] - 2024-10-10

Expand Down
2 changes: 1 addition & 1 deletion cvat-cli/requirements/base.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
cvat-sdk~=2.21.0
cvat-sdk~=2.21.1
Pillow>=10.3.0
setuptools>=70.0.0 # not directly required, pinned by Snyk to avoid a vulnerability
2 changes: 1 addition & 1 deletion cvat-cli/src/cvat_cli/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
VERSION = "2.21.0"
VERSION = "2.21.1"
78 changes: 32 additions & 46 deletions cvat-core/src/frames.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ const frameDataCache: Record<string, {
metaFetchedTimestamp: number;
chunkSize: number;
mode: 'annotation' | 'interpolation';
startFrame: number;
stopFrame: number;
jobStartFrame: number;
decodeForward: boolean;
forwardStep: number;
latestFrameDecodeRequest: number | null;
Expand All @@ -44,7 +43,7 @@ const frameMetaCache: Record<string, Promise<FramesMetaData>> = {};
export class FramesMetaData {
public chunkSize: number;
public deletedFrames: Record<number, boolean>;
public includedFrames: number[];
public includedFrames: number[] | null;
public frameFilter: string;
public frames: {
width: number;
Expand Down Expand Up @@ -170,6 +169,14 @@ export class FramesMetaData {
);
}

getDataFrameNumber(jobRelativeFrame: number): number {
return this.frameStep * jobRelativeFrame + this.startFrame;
}

getJobRelativeFrameNumber(dataFrameNumber: number): number {
return (dataFrameNumber - this.startFrame) / this.frameStep;
}

getUpdated(): Record<string, unknown> {
return this.#updateTrigger.getUpdated(this);
}
Expand Down Expand Up @@ -206,7 +213,7 @@ export class FramesMetaData {

getDataFrameNumbers(): number[] {
if (this.includedFrames) {
return this.includedFrames;
return [...this.includedFrames];
}

return range(this.startFrame, this.stopFrame + 1, this.frameStep);
Expand Down Expand Up @@ -326,18 +333,6 @@ class PrefetchAnalyzer {
}
}

function getDataStartFrame(meta: FramesMetaData, localStartFrame: number): number {
return meta.startFrame - localStartFrame * meta.frameStep;
}

function getDataFrameNumber(frameNumber: number, dataStartFrame: number, step: number): number {
return frameNumber * step + dataStartFrame;
}

function getFrameNumber(dataFrameNumber: number, dataStartFrame: number, step: number): number {
return (dataFrameNumber - dataStartFrame) / step;
}

Object.defineProperty(FrameData.prototype.data, 'implementation', {
value(this: FrameData, onServerRequest) {
return new Promise<{
Expand All @@ -346,21 +341,16 @@ Object.defineProperty(FrameData.prototype.data, 'implementation', {
imageData: ImageBitmap | Blob;
} | Blob>((resolve, reject) => {
const {
meta, provider, prefetchAnalyzer, chunkSize, startFrame,
meta, provider, prefetchAnalyzer, chunkSize, jobStartFrame,
decodeForward, forwardStep, decodedBlocksCacheSize,
} = frameDataCache[this.jobID];

const requestId = +_.uniqueId();
const dataStartFrame = getDataStartFrame(meta, startFrame);
const requestedDataFrameNumber = getDataFrameNumber(
this.number, dataStartFrame, meta.frameStep,
);
const requestedDataFrameNumber = meta.getDataFrameNumber(this.number - jobStartFrame);
const chunkIndex = meta.getFrameChunkIndex(requestedDataFrameNumber);
const segmentFrameNumbers = meta.getDataFrameNumbers().map(
(dataFrameNumber: number) => getFrameNumber(
dataFrameNumber, dataStartFrame, meta.frameStep,
),
);
const segmentFrameNumbers = meta.getDataFrameNumbers().map((dataFrameNumber: number) => (
meta.getJobRelativeFrameNumber(dataFrameNumber) + jobStartFrame
));
const frame = provider.frame(this.number);

function findTheNextNotDecodedChunk(currentFrameIndex: number): number | null {
Expand Down Expand Up @@ -581,7 +571,7 @@ async function saveJobMeta(meta: FramesMetaData, jobID: number): Promise<FramesM
}

function getFrameMeta(jobID, frame): SerializedFramesMetaData['frames'][0] {
const { meta, mode, startFrame } = frameDataCache[jobID];
const { meta, mode, jobStartFrame } = frameDataCache[jobID];
let frameMeta = null;
if (mode === 'interpolation' && meta.frames.length === 1) {
// video tasks have 1 frame info, but image tasks will have many infos
Expand All @@ -590,7 +580,7 @@ function getFrameMeta(jobID, frame): SerializedFramesMetaData['frames'][0] {
if (frame > meta.stopFrame) {
throw new ArgumentError(`Meta information about frame ${frame} can't be received from the server`);
}
frameMeta = meta.frames[frame - startFrame];
frameMeta = meta.frames[frame - jobStartFrame];
} else {
throw new DataError(`Invalid mode is specified ${mode}`);
}
Expand Down Expand Up @@ -639,8 +629,8 @@ export function getContextImage(jobID: number, frame: number): Promise<Record<st

const frameData = frameDataCache[jobID];
const requestId = frame;
const { startFrame } = frameData;
const { related_files: relatedFiles } = frameData.meta.frames[frame - startFrame];
const { jobStartFrame } = frameData;
const { related_files: relatedFiles } = frameData.meta.frames[frame - jobStartFrame];

if (relatedFiles === 0) {
resolve({});
Expand Down Expand Up @@ -726,8 +716,7 @@ export async function getFrame(
chunkType: 'video' | 'imageset',
mode: 'interpolation' | 'annotation', // todo: obsolete, need to remove
frame: number,
startFrame: number,
stopFrame: number,
jobStartFrame: number,
isPlaying: boolean,
step: number,
dimension: DimensionType,
Expand All @@ -750,19 +739,16 @@ export async function getFrame(
Math.floor((2048 * 1024 * 1024) / ((mean + stdDev) * 4 * chunkSize)) || 1, 10,
);

// TODO: migrate to local frame numbers
const dataStartFrame = getDataStartFrame(meta, startFrame);
const dataFrameNumberGetter = (frameNumber: number): number => (
getDataFrameNumber(frameNumber, dataStartFrame, meta.frameStep)
meta.getDataFrameNumber(frameNumber - jobStartFrame)
);

frameDataCache[jobID] = {
meta,
metaFetchedTimestamp: Date.now(),
chunkSize,
mode,
startFrame,
stopFrame,
jobStartFrame,
decodeForward: isPlaying,
forwardStep: step,
provider: new FrameDecoder(
Expand Down Expand Up @@ -864,12 +850,13 @@ export async function findFrame(
let lastUndeletedFrame = null;
const check = (frame): boolean => {
if (meta.includedFrames) {
// meta.includedFrames contains input frame numbers now
const dataStartFrame = meta.startFrame; // this is only true when includedFrames is set
return (meta.includedFrames.includes(
getDataFrameNumber(frame, dataStartFrame, meta.frameStep))
// meta.includedFrames contains absolute frame numbers
const jobStartFrame = 0; // this is only true when includedFrames is set
return (
meta.includedFrames.includes(meta.getDataFrameNumber(frame - jobStartFrame))
) && (!filters.notDeleted || !(frame in meta.deletedFrames));
}

if (filters.notDeleted) {
return !(frame in meta.deletedFrames);
}
Expand All @@ -888,23 +875,22 @@ export async function findFrame(
return lastUndeletedFrame;
}

export function getCachedChunks(jobID): number[] {
export function getCachedChunks(jobID: number): number[] {
if (!(jobID in frameDataCache)) {
return [];
}

return frameDataCache[jobID].provider.cachedChunks(true);
}

export function getJobFrameNumbers(jobID): number[] {
export function getJobFrameNumbers(jobID: number): number[] {
if (!(jobID in frameDataCache)) {
return [];
}

const { meta, startFrame } = frameDataCache[jobID];
const dataStartFrame = getDataStartFrame(meta, startFrame);
const { meta, jobStartFrame } = frameDataCache[jobID];
return meta.getDataFrameNumbers().map((dataFrameNumber: number): number => (
getFrameNumber(dataFrameNumber, dataStartFrame, meta.frameStep)
meta.getJobRelativeFrameNumber(dataFrameNumber) + jobStartFrame
));
}

Expand Down
2 changes: 0 additions & 2 deletions cvat-core/src/session-implementation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,6 @@ export function implementJob(Job: typeof JobClass): typeof JobClass {
this.mode,
frame,
this.startFrame,
this.stopFrame,
isPlaying,
step,
this.dimension,
Expand Down Expand Up @@ -860,7 +859,6 @@ export function implementTask(Task: typeof TaskClass): typeof TaskClass {
this.mode,
frame,
job.startFrame,
job.stopFrame,
isPlaying,
step,
this.dimension,
Expand Down
2 changes: 1 addition & 1 deletion cvat-sdk/gen/generate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ set -e

GENERATOR_VERSION="v6.0.1"

VERSION="2.21.0"
VERSION="2.21.1"
LIB_NAME="cvat_sdk"
LAYER1_LIB_NAME="${LIB_NAME}/api_client"
DST_DIR="$(cd "$(dirname -- "$0")/.." && pwd)"
Expand Down
2 changes: 1 addition & 1 deletion cvat-ui/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cvat-ui",
"version": "1.66.0",
"version": "1.66.1",
"description": "CVAT single-page application",
"main": "src/index.tsx",
"scripts": {
Expand Down
4 changes: 3 additions & 1 deletion cvat-ui/src/actions/annotation-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -651,7 +651,7 @@ export function changeFrameAsync(
return;
}

if (!isAbleToChangeFrame() || statisticsVisible || propagateVisible) {
if (!isAbleToChangeFrame(toFrame) || statisticsVisible || propagateVisible) {
return;
}

Expand Down Expand Up @@ -914,6 +914,7 @@ export function getJobAsync({
}
}

const jobMeta = await cvat.frames.getMeta('job', job.id);
// frame query parameter does not work for GT job
const frameNumber = Number.isInteger(initialFrame) && gtJob?.id !== job.id ?
initialFrame as number :
Expand Down Expand Up @@ -959,6 +960,7 @@ export function getJobAsync({
payload: {
openTime,
job,
jobMeta,
queryParameters,
groundTruthInstance: gtJob || null,
groundTruthJobFramesMeta,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ function AttributeAnnotationSidebar(props: StateToProps & DispatchToProps): JSX.
if (activeObjectState && activeObjectState.objectType === ObjectType.TRACK) {
const frame =
typeof activeObjectState.keyframes.next === 'number' ? activeObjectState.keyframes.next : null;
if (frame !== null && isAbleToChangeFrame()) {
if (frame !== null && isAbleToChangeFrame(frame)) {
changeFrame(frame);
}
}
Expand All @@ -326,7 +326,7 @@ function AttributeAnnotationSidebar(props: StateToProps & DispatchToProps): JSX.
if (activeObjectState && activeObjectState.objectType === ObjectType.TRACK) {
const frame =
typeof activeObjectState.keyframes.prev === 'number' ? activeObjectState.keyframes.prev : null;
if (frame !== null && isAbleToChangeFrame()) {
if (frame !== null && isAbleToChangeFrame(frame)) {
changeFrame(frame);
}
}
Expand Down
Loading

0 comments on commit 4a7e8e0

Please sign in to comment.