Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Quality control page #8329

Merged
merged 100 commits into from
Sep 11, 2024
Merged
Show file tree
Hide file tree
Changes from 62 commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
1f28607
initial commit
klakhov Jul 16, 2024
0350e61
update quality form view
klakhov Jul 16, 2024
0ce7e60
Merge branch 'develop' into kl/support-quality-plugin
klakhov Jul 16, 2024
7e39916
moved quality tab to quality control page
klakhov Jul 17, 2024
e4e16f4
added support for plugin tabs
klakhov Jul 17, 2024
c096c1d
changed yellow quality color
klakhov Jul 18, 2024
6c458e3
Merge branch 'develop' into kl/support-quality-plugin
klakhov Jul 19, 2024
09f22a6
style control improvements
klakhov Jul 19, 2024
7e38402
demo implementation
klakhov Jul 24, 2024
7b03b28
Merge branch 'develop' into kl/support-quality-plugin
klakhov Jul 24, 2024
4d40228
small fix
klakhov Jul 24, 2024
0d41ac7
Merge branch 'develop' into kl/support-quality-plugin
klakhov Jul 25, 2024
f4c747b
moved sorter to table utils
klakhov Jul 25, 2024
097c006
added new quality settings params
klakhov Jul 25, 2024
ff472bf
added support of colors corresponding to target threshold
klakhov Jul 25, 2024
ddc1b61
Merge branch 'develop' into kl/support-quality-plugin
klakhov Jul 31, 2024
04fb850
made quality form public
klakhov Aug 1, 2024
b7e8900
implemented paid placeholder, management tab overload
klakhov Aug 3, 2024
8295dbc
added overview plugin
klakhov Aug 4, 2024
0e963ef
moved overview to plugin
klakhov Aug 5, 2024
ce7c5a3
Merge branch 'develop' into kl/support-quality-plugin
klakhov Aug 8, 2024
d9c5090
supported using job card in plugin
klakhov Aug 8, 2024
39d9c8e
merge develop
klakhov Aug 12, 2024
0fb99f0
moved quality report calculation
klakhov Aug 12, 2024
3a749c7
moved job validation count to plugin
klakhov Aug 13, 2024
16c6e2f
Merge branch 'develop' into kl/support-quality-plugin
klakhov Aug 19, 2024
c0f0d2f
Job validations - common
zhiltsov-max Aug 19, 2024
da2d9fb
Update changelog
zhiltsov-max Aug 19, 2024
65b4591
Remove unused imports
zhiltsov-max Aug 19, 2024
c5fa228
Update test assets
zhiltsov-max Aug 19, 2024
bf09a38
Update server schema
zhiltsov-max Aug 19, 2024
abb214f
Fix formatting
zhiltsov-max Aug 20, 2024
5bff076
removed quality components
klakhov Aug 20, 2024
042709e
updated ground truth test
klakhov Aug 20, 2024
1feede8
Merge branch 'develop' into kl/support-quality-plugin
klakhov Aug 21, 2024
56a8e3b
Merge branch 'kl/quality-plugin-remove-analytics' into kl/support-qua…
klakhov Aug 21, 2024
8bac234
Merge branch 'zm/validation-api' into kl/support-quality-plugin
klakhov Aug 21, 2024
1d29c2f
Refactor field definition
zhiltsov-max Aug 21, 2024
d81e1da
Update server schema
zhiltsov-max Aug 21, 2024
b9ca46c
Merge branch 'develop' into zm/validation-api
zhiltsov-max Aug 21, 2024
b96bb72
adapted settings for new API
klakhov Aug 21, 2024
3a40c2f
added fetching job meta, showing summary component
klakhov Aug 22, 2024
82fdfb9
added allocation table, styles
klakhov Aug 22, 2024
3ce0864
Merge branch 'develop' into zm/validation-api
zhiltsov-max Aug 23, 2024
7df74bb
implemented actual frame deleting/restoring from management page
klakhov Aug 23, 2024
6db52f3
fixed group operations
klakhov Aug 23, 2024
f036ace
Merge branch 'zm/validation-api' into kl/support-quality-plugin
klakhov Aug 23, 2024
d4fb8fa
refactor quality control page
klakhov Aug 23, 2024
5e941ae
fixed count on summary component
klakhov Aug 23, 2024
8b46b85
fixed styles of paid placeholder
klakhov Aug 24, 2024
ab2e42f
added react resizible dep
klakhov Aug 24, 2024
38536bd
fixed types
klakhov Aug 24, 2024
04d4e82
Merge branch 'develop' into kl/support-quality-plugin
klakhov Aug 26, 2024
cf75c91
added settings for paid placeholder
klakhov Aug 26, 2024
a6b9707
fixed eslint
klakhov Aug 26, 2024
17e1f81
fix some minor issues
klakhov Aug 26, 2024
9872394
package & changelog
klakhov Aug 26, 2024
edad81a
added plugin column
klakhov Aug 26, 2024
ed72d7a
fixed linter
klakhov Aug 26, 2024
84ba53d
added plugin for management page
klakhov Aug 26, 2024
d69a92c
minor cleanup
klakhov Aug 26, 2024
51ea349
updated quality settings descriptions
klakhov Aug 26, 2024
7e8c44d
minor bugfixes
klakhov Aug 26, 2024
0a44763
applied coderabbit comments
klakhov Aug 26, 2024
8c4eb52
fixed multitask bug
klakhov Aug 26, 2024
bacafe5
added plugin for sorting columns
klakhov Aug 26, 2024
3e89c5f
adapted quality settings changes
klakhov Aug 27, 2024
ec38612
supported target metric in plugin
klakhov Aug 27, 2024
823e921
support for table actions plugins
klakhov Aug 28, 2024
32145ad
Resolved conflicts
bsekachev Sep 3, 2024
573053b
Accidently removed yarn.lock
bsekachev Sep 3, 2024
2c3e301
Updated yarn
bsekachev Sep 3, 2024
9d98964
Minor updates
bsekachev Sep 3, 2024
b66971e
cvat-core refactoring
bsekachev Sep 4, 2024
54d7601
Refactoring adding a gt task
bsekachev Sep 4, 2024
d7a8c7b
Fixed condition
bsekachev Sep 4, 2024
28f0a04
Do not store placeholder image in the bundle
bsekachev Sep 4, 2024
13c300c
Merge branch 'develop' into kl/support-quality-plugin
bsekachev Sep 5, 2024
696082d
Fixed different issues found in task creation form
bsekachev Sep 5, 2024
86480ee
Added missed field
bsekachev Sep 5, 2024
456062e
Aborted unnecessary changes
bsekachev Sep 5, 2024
418202d
Aborted extra changes
bsekachev Sep 5, 2024
e84b6b8
Fixed imports
bsekachev Sep 5, 2024
5ea5a0a
Reduced code duplication
bsekachev Sep 5, 2024
7a22d16
Do not render quality block
bsekachev Sep 5, 2024
a9d7010
Removed duplicated elements
bsekachev Sep 5, 2024
1e07d34
Fixed classes
bsekachev Sep 5, 2024
59bdcde
Renamed classes
bsekachev Sep 5, 2024
1020819
minor fix
bsekachev Sep 5, 2024
4b0b0ba
Merge branch 'develop' into kl/support-quality-plugin
bsekachev Sep 5, 2024
31cbd5a
Minor codestyle fixes
bsekachev Sep 5, 2024
5884866
Minor fixes
bsekachev Sep 5, 2024
29ce9a6
Updated for plugin
bsekachev Sep 8, 2024
40a80d7
Handle useProjectCloudStorage switch
bsekachev Sep 8, 2024
86f7999
Merged develop
bsekachev Sep 9, 2024
953e3d4
Updated styles on long tables
bsekachev Sep 9, 2024
a41db37
Some code refactoring
bsekachev Sep 10, 2024
dd1be67
Merge branch 'develop' into kl/support-quality-plugin
bsekachev Sep 10, 2024
4f20729
Adjusted for plugin
bsekachev Sep 11, 2024
489c216
Merge branch 'develop' into kl/support-quality-plugin
bsekachev Sep 11, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions changelog.d/20240826_093730_klakhov_support_quality_plugin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
### Changed

- Moved quality control from `analytics` page to `quality control` page
(<https://github.com/cvat-ai/cvat/pull/8329>)

### Removed

- Quality report no longer available in CVAT community version
(<https://github.com/cvat-ai/cvat/pull/8329>)

### Added

- Quality management tab on `quality control` allowing to enable/disable GT frames
(<https://github.com/cvat-ai/cvat/pull/8329>)
2 changes: 1 addition & 1 deletion cvat-core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cvat-core",
"version": "15.1.2",
"version": "15.2.0",
"type": "module",
"description": "Part of Computer Vision Tool which presents an interface for client-side integration",
"main": "src/api.ts",
Expand Down
17 changes: 11 additions & 6 deletions cvat-core/src/api-implementation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import {
import QualityReport from './quality-report';
import QualityConflict, { ConflictSeverity } from './quality-conflict';
import QualitySettings from './quality-settings';
import { FramesMetaData } from './frames';
import { FramesMetaData, getJobMeta } from './frames';
import AnalyticsReport from './analytics-report';
import { listActions, registerAction, runActions } from './annotations-actions';
import { JobType } from './enums';
Expand Down Expand Up @@ -550,11 +550,16 @@ export default function implementAPI(cvat: CVATCore): CVATCore {
await serverProxy.analytics.performance.calculate(params, onUpdate);
});
implementationMixin(cvat.frames.getMeta, async (type, id) => {
const result = await serverProxy.frames.getMeta(type, id);
return new FramesMetaData({
...result,
deleted_frames: Object.fromEntries(result.deleted_frames.map((_frame) => [_frame, true])),
});
if (type === 'task') {
const result = await serverProxy.frames.getMeta(type, id);
return new FramesMetaData({
...result,
deleted_frames: Object.fromEntries(result.deleted_frames.map((_frame) => [_frame, true])),
});
}

const result = await getJobMeta(id, { reload: true });
return result;
});

return cvat;
Expand Down
21 changes: 11 additions & 10 deletions cvat-core/src/frames.ts
Original file line number Diff line number Diff line change
Expand Up @@ -435,8 +435,8 @@ Object.defineProperty(FrameData.prototype.data, 'implementation', {
writable: false,
});

async function getJobMeta(jobID: number): Promise<FramesMetaData> {
if (!frameMetaCache[jobID]) {
export async function getJobMeta(jobID: number, { reload } = { reload: false }): Promise<FramesMetaData> {
if (!frameMetaCache[jobID] || reload) {
frameMetaCache[jobID] = serverProxy.frames.getMeta('job', jobID)
.then((serverMeta) => new FramesMetaData({
...serverMeta,
Expand Down Expand Up @@ -655,24 +655,25 @@ export async function getDeletedFrames(instanceType: 'job' | 'task', id): Promis
throw new Exception(`getDeletedFrames is not implemented for ${instanceType}`);
}

export function deleteFrame(jobID: number, frame: number): void {
const { meta } = frameDataCache[jobID];
export async function deleteFrame(jobID: number, frame: number): Promise<void> {
const meta = await frameMetaCache[jobID];
meta.deletedFrames[frame] = true;
}

export function restoreFrame(jobID: number, frame: number): void {
const { meta } = frameDataCache[jobID];
export async function restoreFrame(jobID: number, frame: number): Promise<void> {
const meta = await frameMetaCache[jobID];
delete meta.deletedFrames[frame];
}

export async function patchMeta(jobID: number): Promise<void> {
const { meta } = frameDataCache[jobID];
export async function patchMeta(jobID: number): Promise<FramesMetaData> {
const meta = await frameMetaCache[jobID];
const updatedFields = meta.getUpdated();

if (Object.keys(updatedFields).length) {
const newMeta = await saveJobMeta(meta, jobID);
frameDataCache[jobID].meta = newMeta;
frameMetaCache[jobID] = saveJobMeta(meta, jobID);
}
const newMeta = await frameMetaCache[jobID];
return newMeta;
}

export async function findFrame(
Expand Down
45 changes: 43 additions & 2 deletions cvat-core/src/quality-settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,17 @@ import { SerializedQualitySettingsData } from './server-response-types';
import PluginRegistry from './plugins';
import serverProxy from './server-proxy';

export enum TargetMetric {
ACCURACY = 'accuracy',
PRECISION = 'precision',
RECALL = 'recall',
}

export default class QualitySettings {
#id: number;
#targetMetric: TargetMetric;
#targetMetricThreshold: number;
#maxValidationsPerJob: number;
#task: number;
#iouThreshold: number;
#oksSigma: number;
Expand All @@ -25,6 +34,9 @@ export default class QualitySettings {
constructor(initialData: SerializedQualitySettingsData) {
this.#id = initialData.id;
this.#task = initialData.task;
this.#targetMetric = initialData.target_metric as TargetMetric;
this.#targetMetricThreshold = initialData.target_metric_threshold;
this.#maxValidationsPerJob = initialData.max_validations_per_job;
this.#iouThreshold = initialData.iou_threshold;
this.#oksSigma = initialData.oks_sigma;
this.#lineThickness = initialData.line_thickness;
Expand Down Expand Up @@ -143,6 +155,30 @@ export default class QualitySettings {
this.#compareAttributes = newVal;
}

get targetMetric(): TargetMetric {
return this.#targetMetric;
}

set targetMetric(newVal: TargetMetric) {
this.#targetMetric = newVal;
}

get targetMetricThreshold(): number {
return this.#targetMetricThreshold;
}

set targetMetricThreshold(newVal: number) {
this.#targetMetricThreshold = newVal;
}

get maxValidationsPerJob(): number {
return this.#maxValidationsPerJob;
}

set maxValidationsPerJob(newVal: number) {
this.#maxValidationsPerJob = newVal;
}

public toJSON(): SerializedQualitySettingsData {
const result: SerializedQualitySettingsData = {
iou_threshold: this.#iouThreshold,
Expand All @@ -157,6 +193,9 @@ export default class QualitySettings {
object_visibility_threshold: this.#objectVisibilityThreshold,
panoptic_comparison: this.#panopticComparison,
compare_attributes: this.#compareAttributes,
target_metric: this.#targetMetric,
target_metric_threshold: this.#targetMetricThreshold,
max_validations_per_job: this.#maxValidationsPerJob,
};

return result;
Expand All @@ -172,8 +211,10 @@ Object.defineProperties(QualitySettings.prototype.save, {
implementation: {
writable: false,
enumerable: false,
value: async function implementation() {
const result = await serverProxy.analytics.quality.settings.update(this.id, this.toJSON());
value: async function implementation(): Promise<QualitySettings> {
const result = await serverProxy.analytics.quality.settings.update(
this.id, this.toJSON(),
);
return new QualitySettings(result);
},
},
Expand Down
3 changes: 3 additions & 0 deletions cvat-core/src/server-response-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,9 @@ export type QualitySettingsFilter = Camelized<APIQualitySettingsFilter>;
export interface SerializedQualitySettingsData {
id?: number;
task?: number;
target_metric?: string;
target_metric_threshold?: number;
max_validations_per_job?: number;
iou_threshold?: number;
oks_sigma?: number;
line_thickness?: number;
Expand Down
34 changes: 25 additions & 9 deletions cvat-core/src/session-implementation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,11 @@ async function deleteFrameWrapper(jobID, frame): Promise<void> {
};

await redo();
getHistory(this).do(HistoryActions.REMOVED_FRAME, async () => {
restoreFrame(jobID, frame);
}, redo, [], frame);
try {
getHistory(this).do(HistoryActions.REMOVED_FRAME, async () => {
restoreFrame(jobID, frame);
}, redo, [], frame);
} catch (error) { /* empty */ }
}

async function restoreFrameWrapper(jobID, frame): Promise<void> {
Expand All @@ -55,9 +57,11 @@ async function restoreFrameWrapper(jobID, frame): Promise<void> {
};

await redo();
getHistory(this).do(HistoryActions.RESTORED_FRAME, async () => {
deleteFrame(jobID, frame);
}, redo, [], frame);
try {
getHistory(this).do(HistoryActions.RESTORED_FRAME, async () => {
deleteFrame(jobID, frame);
}, redo, [], frame);
} catch (error) { /* empty */ }
}

export function implementJob(Job: typeof JobClass): typeof JobClass {
Expand Down Expand Up @@ -232,7 +236,7 @@ export function implementJob(Job: typeof JobClass): typeof JobClass {
value: function saveFramesImplementation(
this: JobClass,
): ReturnType<typeof JobClass.prototype.frames.save> {
return patchMeta(this.id);
return patchMeta(this.id).then((meta) => [meta]);
},
});

Expand Down Expand Up @@ -695,6 +699,19 @@ export function implementTask(Task: typeof TaskClass): typeof TaskClass {
taskSpec.source_storage = this.sourceStorage.toJSON();
}

if (this.validationMethod !== 'undefined') {
taskSpec.validation_method = this.validationMethod;
}
if (typeof this.validationFramesPercent !== 'undefined') {
taskSpec.validation_frames_percent = this.validationFramesPercent;
}
if (typeof this.validationFramesPerJob !== 'undefined') {
taskSpec.validation_frames_per_job = this.validationFramesPerJob;
}
if (typeof this.frameSelectionMethod !== 'undefined') {
taskSpec.frame_selection_method = this.frameSelectionMethod;
}

const taskDataSpec = {
client_files: this.clientFiles,
server_files: this.serverFiles,
Expand Down Expand Up @@ -899,8 +916,7 @@ export function implementTask(Task: typeof TaskClass): typeof TaskClass {
value: async function saveFramesImplementation(
this: TaskClass,
): ReturnType<typeof TaskClass.prototype.frames.save> {
return Promise.all(this.jobs.map((job) => patchMeta(job.id)))
.then(() => Promise.resolve());
return Promise.all(this.jobs.map((job) => patchMeta(job.id)));
},
});

Expand Down
29 changes: 25 additions & 4 deletions cvat-core/src/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {
SerializedLabel, SerializedTask,
} from './server-response-types';
import AnnotationGuide from './guide';
import { FrameData } from './frames';
import { FrameData, FramesMetaData } from './frames';
import Statistics from './statistics';
import { Request } from './request';
import logger from './logger';
Expand Down Expand Up @@ -223,10 +223,11 @@ function buildDuplicatedAPI(prototype) {
);
},
async save() {
await PluginRegistry.apiWrapper.call(
const result = await PluginRegistry.apiWrapper.call(
this,
prototype.frames.save,
);
return result;
},
async cachedChunks() {
const result = await PluginRegistry.apiWrapper.call(this, prototype.frames.cachedChunks);
Expand Down Expand Up @@ -377,7 +378,7 @@ export class Session {
get: (frame: number, isPlaying?: boolean, step?: number) => Promise<FrameData>;
delete: (frame: number) => Promise<void>;
restore: (frame: number) => Promise<void>;
save: () => Promise<void>;
save: () => Promise<FramesMetaData[]>;
cachedChunks: () => Promise<number[]>;
preview: () => Promise<string>;
contextImage: (frame: number) => Promise<Record<string, ImageBitmap>>;
Expand Down Expand Up @@ -730,6 +731,11 @@ export class Task extends Session {
public readonly cloudStorageID: number;
public readonly sortingMethod: string;

public readonly validationMethod: string;
public readonly validationFramesPercent: number;
public readonly validationFramesPerJob: number;
public readonly frameSelectionMethod: string;

constructor(initialData: Readonly<Omit<SerializedTask, 'labels' | 'jobs'> & {
labels?: SerializedLabel[];
progress?: SerializedTask['jobs'];
Expand Down Expand Up @@ -775,7 +781,10 @@ export class Task extends Session {
sorting_method: undefined,
files: undefined,

quality_settings: undefined,
validation_method: undefined,
validation_frames_percent: undefined,
validation_frames_per_job: undefined,
frame_selection_method: undefined,
};

const updateTrigger = new FieldUpdateTrigger();
Expand Down Expand Up @@ -1103,6 +1112,18 @@ export class Task extends Session {
progress: {
get: () => data.progress,
},
validationFramesPercent: {
get: () => data.validation_frames_percent,
},
validationFramesPerJob: {
get: () => data.validation_frames_per_job,
},
frameSelectionMethod: {
get: () => data.frame_selection_method,
},
validationMethod: {
get: () => data.validation_method,
},
_internalData: {
get: () => data,
},
Expand Down
4 changes: 3 additions & 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.65.0",
"version": "1.66.0",
"description": "CVAT single-page application",
"main": "src/index.tsx",
"scripts": {
Expand Down Expand Up @@ -35,6 +35,7 @@
"@types/react-router-dom": "^5.1.9",
"@types/redux-logger": "^3.0.9",
"@types/resize-observer-browser": "^0.1.6",
"@types/react-resizable": "^3.0.8",
"@uiw/react-md-editor": "^3.22.0",
"antd": "5.17.1",
"chart.js": "^4.3.0",
Expand All @@ -59,6 +60,7 @@
"react-markdown": "^8.0.4",
"react-moment": "^1.1.1",
"react-redux": "^8.0.2",
"react-resizable": "^3.0.5",
"react-router": "^5.1.0",
"react-router-dom": "^5.1.0",
"react-sortable-hoc": "^2.0.0",
Expand Down
12 changes: 11 additions & 1 deletion cvat-ui/src/actions/tasks-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
import { filterNull } from 'utils/filter-null';
import { ThunkDispatch, ThunkAction } from 'utils/redux';

import { ValidationMethod } from 'components/create-task-page/quality-configuration-form';
import { getInferenceStatusAsync } from './models-actions';
import { updateRequestProgress } from './requests-actions';

Expand Down Expand Up @@ -254,11 +255,20 @@ ThunkAction {
description.cloud_storage_id = data.cloudStorageId;
}

if (data.quality.validationMethod === ValidationMethod.GT) {
description.validation_method = ValidationMethod.GT;
description.validation_frames_percent = data.quality.validationFramesPercent;
description.frame_selection_method = data.quality.frameSelectionMethod;
} else if (data.quality.validationMethod === ValidationMethod.HONEYPOTS) {
description.validation_method = ValidationMethod.HONEYPOTS;
description.validation_frames_percent = data.quality.validationFramesPercent;
description.validation_frames_per_job = data.quality.validationFramesPerJob;
}

const taskInstance = new cvat.classes.Task(description);
taskInstance.clientFiles = data.files.local;
taskInstance.serverFiles = data.files.share.concat(data.files.cloudStorage);
taskInstance.remoteFiles = data.files.remote;

try {
const savedTask = await taskInstance.save({
requestStatusCallback(request) {
Expand Down
1 change: 1 addition & 0 deletions cvat-ui/src/assets/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
// SPDX-License-Identifier: MIT

declare module '*.svg';
declare module '*.png';
Binary file added cvat-ui/src/assets/paid-feature.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading