Skip to content

Commit

Permalink
Merge branch 'develop' into zm/cli-infer-host-schema
Browse files Browse the repository at this point in the history
  • Loading branch information
Maxim Zhiltsov authored Sep 29, 2020
2 parents 3cbbad8 + 5052737 commit 990f61d
Show file tree
Hide file tree
Showing 43 changed files with 494 additions and 87 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- [Datumaro] CLI command for dataset equality comparison (<https://github.com/opencv/cvat/pull/1989>)
- [Datumaro] Merging of datasets with different labels (<https://github.com/opencv/cvat/pull/2098>)
- Add FBRS interactive segmentation serverless function (<https://github.com/openvinotoolkit/cvat/pull/2094>)
- Ability to change default behaviour of previous/next buttons of a player.
It supports regular navigation, searching a frame according to annotations
filters and searching the nearest frame without any annotations (<https://github.com/openvinotoolkit/cvat/pull/2221>)
- MacOS users notes in CONTRIBUTING.md

### Changed
Expand All @@ -23,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Right colors of label tags in label mapping when a user runs automatic detection (<https://github.com/openvinotoolkit/cvat/pull/2162>)
- Nuclio became an optional component of CVAT (<https://github.com/openvinotoolkit/cvat/pull/2192>)
- A key to remove a point from a polyshape [Ctrl => Alt] (<https://github.com/openvinotoolkit/cvat/pull/2204>)
- Updated `docker-compose` file version from `2.3` to `3.3`(<https://github.com/openvinotoolkit/cvat/pull/2235>)
- Added auto inference of url schema from host in CLI, if provided (<https://github.com/openvinotoolkit/cvat/pull/2240>)

### Deprecated
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ Server = nuclio
}
]
```

</details>
### Run Cypress tests
- Install Сypress as described in the [documentation](https://docs.cypress.io/guides/getting-started/installing-cypress.html).
- Run cypress tests:
Expand Down
2 changes: 1 addition & 1 deletion components/analytics/docker-compose.analytics.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version: '2.3'
version: '3.3'
services:
cvat_elasticsearch:
container_name: cvat_elasticsearch
Expand Down
2 changes: 1 addition & 1 deletion components/serverless/docker-compose.serverless.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version: '2.3'
version: '3.3'
services:
serverless:
container_name: nuclio
Expand Down
37 changes: 37 additions & 0 deletions cvat-core/src/annotations-collection.js
Original file line number Diff line number Diff line change
Expand Up @@ -848,6 +848,43 @@
};
}

searchEmpty(frameFrom, frameTo) {
const sign = Math.sign(frameTo - frameFrom);
const predicate = sign > 0
? (frame) => frame <= frameTo
: (frame) => frame >= frameTo;
const update = sign > 0
? (frame) => frame + 1
: (frame) => frame - 1;
for (let frame = frameFrom; predicate(frame); frame = update(frame)) {
if (frame in this.shapes && this.shapes[frame].some((shape) => !shape.removed)) {
continue;
}
if (frame in this.tags && this.tags[frame].some((tag) => !tag.removed)) {
continue;
}
const filteredTracks = this.tracks.filter((track) => !track.removed);
let found = false;
for (const track of filteredTracks) {
const keyframes = track.boundedKeyframes(frame);
const { prev, first } = keyframes;
const last = prev === null ? first : prev;
const lastShape = track.shapes[last];
const isKeyfame = frame in track.shapes;
if (first <= frame && (!lastShape.outside || isKeyfame)) {
found = true;
break;
}
}

if (found) continue;

return frame;
}

return null;
}

search(filters, frameFrom, frameTo) {
const [groups, query] = this.annotationsFilter.toJSONQuery(filters);
const sign = Math.sign(frameTo - frameFrom);
Expand Down
4 changes: 3 additions & 1 deletion cvat-core/src/annotations-objects.js
Original file line number Diff line number Diff line change
Expand Up @@ -932,7 +932,9 @@
}, [this.clientID], frame);
}

_appendShapeActionToHistory(actionType, frame, undoShape, redoShape, undoSource, redoSource) {
_appendShapeActionToHistory(
actionType, frame, undoShape, redoShape, undoSource, redoSource,
) {
this.history.do(actionType, () => {
if (!undoShape) {
delete this.shapes[frame];
Expand Down
14 changes: 14 additions & 0 deletions cvat-core/src/annotations.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,19 @@
);
}

function searchEmptyFrame(session, frameFrom, frameTo) {
const sessionType = session instanceof Task ? 'task' : 'job';
const cache = getCache(sessionType);

if (cache.has(session)) {
return cache.get(session).collection.searchEmpty(frameFrom, frameTo);
}

throw new DataError(
'Collection has not been initialized yet. Call annotations.get() or annotations.clear(true) before',
);
}

function mergeAnnotations(session, objectStates) {
const sessionType = session instanceof Task ? 'task' : 'job';
const cache = getCache(sessionType);
Expand Down Expand Up @@ -373,6 +386,7 @@
hasUnsavedChanges,
mergeAnnotations,
searchAnnotations,
searchEmptyFrame,
splitAnnotations,
groupAnnotations,
clearAnnotations,
Expand Down
8 changes: 6 additions & 2 deletions cvat-core/src/api-implementation.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,19 @@
await serverProxy.server.logout();
};

cvat.server.changePassword.implementation = async (oldPassword, newPassword1, newPassword2) => {
cvat.server.changePassword.implementation = async (
oldPassword, newPassword1, newPassword2,
) => {
await serverProxy.server.changePassword(oldPassword, newPassword1, newPassword2);
};

cvat.server.requestPasswordReset.implementation = async (email) => {
await serverProxy.server.requestPasswordReset(email);
};

cvat.server.resetPassword.implementation = async(newPassword1, newPassword2, uid, token) => {
cvat.server.resetPassword.implementation = async (
newPassword1, newPassword2, uid, token,
) => {
await serverProxy.server.resetPassword(newPassword1, newPassword2, uid, token);
};

Expand Down
4 changes: 3 additions & 1 deletion cvat-core/src/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,9 @@ function build() {
*/
async changePassword(oldPassword, newPassword1, newPassword2) {
const result = await PluginRegistry
.apiWrapper(cvat.server.changePassword, oldPassword, newPassword1, newPassword2);
.apiWrapper(
cvat.server.changePassword, oldPassword, newPassword1, newPassword2,
);
return result;
},
/**
Expand Down
6 changes: 3 additions & 3 deletions cvat-core/src/enums.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
* @property {string} UNKNOWN 'unknown'
* @readonly
*/
const RQStatus = Object.freeze({
const RQStatus = Object.freeze({
QUEUED: 'queued',
STARTED: 'started',
FINISHED: 'finished',
Expand Down Expand Up @@ -134,8 +134,8 @@
* @readonly
*/
const Source = Object.freeze({
MANUAL:'manual',
AUTO:'auto',
MANUAL: 'manual',
AUTO: 'auto',
});

/**
Expand Down
68 changes: 68 additions & 0 deletions cvat-core/src/session.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,13 @@
return result;
},

async searchEmpty(frameFrom, frameTo) {
const result = await PluginRegistry
.apiWrapper.call(this, prototype.annotations.searchEmpty,
frameFrom, frameTo);
return result;
},

async select(objectStates, x, y) {
const result = await PluginRegistry
.apiWrapper.call(this,
Expand Down Expand Up @@ -347,6 +354,18 @@
* @instance
* @async
*/
/**
* Find the nearest empty frame without any annotations
* @method searchEmpty
* @memberof Session.annotations
* @param {integer} from lower bound of a search
* @param {integer} to upper bound of a search
* @returns {integer|null} a frame that contains objects according to the filter
* @throws {module:API.cvat.exceptions.PluginError}
* @throws {module:API.cvat.exceptions.ArgumentError}
* @instance
* @async
*/
/**
* Select shape under a cursor by using minimal distance
* between a cursor and a shape edge or a shape point
Expand Down Expand Up @@ -746,6 +765,7 @@
group: Object.getPrototypeOf(this).annotations.group.bind(this),
clear: Object.getPrototypeOf(this).annotations.clear.bind(this),
search: Object.getPrototypeOf(this).annotations.search.bind(this),
searchEmpty: Object.getPrototypeOf(this).annotations.searchEmpty.bind(this),
upload: Object.getPrototypeOf(this).annotations.upload.bind(this),
select: Object.getPrototypeOf(this).annotations.select.bind(this),
import: Object.getPrototypeOf(this).annotations.import.bind(this),
Expand Down Expand Up @@ -1318,6 +1338,7 @@
group: Object.getPrototypeOf(this).annotations.group.bind(this),
clear: Object.getPrototypeOf(this).annotations.clear.bind(this),
search: Object.getPrototypeOf(this).annotations.search.bind(this),
searchEmpty: Object.getPrototypeOf(this).annotations.searchEmpty.bind(this),
upload: Object.getPrototypeOf(this).annotations.upload.bind(this),
select: Object.getPrototypeOf(this).annotations.select.bind(this),
import: Object.getPrototypeOf(this).annotations.import.bind(this),
Expand Down Expand Up @@ -1411,6 +1432,7 @@
saveAnnotations,
hasUnsavedChanges,
searchAnnotations,
searchEmptyFrame,
mergeAnnotations,
splitAnnotations,
groupAnnotations,
Expand Down Expand Up @@ -1537,6 +1559,29 @@
return result;
};

Job.prototype.annotations.searchEmpty.implementation = function (frameFrom, frameTo) {
if (!Number.isInteger(frameFrom) || !Number.isInteger(frameTo)) {
throw new ArgumentError(
'The start and end frames both must be an integer',
);
}

if (frameFrom < this.startFrame || frameFrom > this.stopFrame) {
throw new ArgumentError(
'The start frame is out of the job',
);
}

if (frameTo < this.startFrame || frameTo > this.stopFrame) {
throw new ArgumentError(
'The stop frame is out of the job',
);
}

const result = searchEmptyFrame(this, frameFrom, frameTo);
return result;
};

Job.prototype.annotations.save.implementation = async function (onUpdate) {
const result = await saveAnnotations(this, onUpdate);
return result;
Expand Down Expand Up @@ -1807,6 +1852,29 @@
return result;
};

Task.prototype.annotations.searchEmpty.implementation = function (frameFrom, frameTo) {
if (!Number.isInteger(frameFrom) || !Number.isInteger(frameTo)) {
throw new ArgumentError(
'The start and end frames both must be an integer',
);
}

if (frameFrom < 0 || frameFrom >= this.size) {
throw new ArgumentError(
'The start frame is out of the task',
);
}

if (frameTo < 0 || frameTo >= this.size) {
throw new ArgumentError(
'The stop frame is out of the task',
);
}

const result = searchEmptyFrame(this, frameFrom, frameTo);
return result;
};

Task.prototype.annotations.save.implementation = async function (onUpdate) {
const result = await saveAnnotations(this, onUpdate);
return result;
Expand Down
2 changes: 1 addition & 1 deletion cvat-core/src/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@
* @readonly
* @instance
*/
get: () => !data.email_verification_required,
get: () => !data.email_verification_required,
},
}));
}
Expand Down
2 changes: 1 addition & 1 deletion cvat-ui/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

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.9.7",
"version": "1.9.8",
"description": "CVAT single-page application",
"main": "src/index.tsx",
"scripts": {
Expand Down
23 changes: 23 additions & 0 deletions cvat-ui/src/actions/annotation-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ export enum AnnotationActionTypes {
SWITCH_Z_LAYER = 'SWITCH_Z_LAYER',
ADD_Z_LAYER = 'ADD_Z_LAYER',
SEARCH_ANNOTATIONS_FAILED = 'SEARCH_ANNOTATIONS_FAILED',
SEARCH_EMPTY_FRAME_FAILED = 'SEARCH_EMPTY_FRAME_FAILED',
CHANGE_WORKSPACE = 'CHANGE_WORKSPACE',
SAVE_LOGS_SUCCESS = 'SAVE_LOGS_SUCCESS',
SAVE_LOGS_FAILED = 'SAVE_LOGS_FAILED',
Expand Down Expand Up @@ -1331,6 +1332,28 @@ export function searchAnnotationsAsync(
};
}

export function searchEmptyFrameAsync(
sessionInstance: any,
frameFrom: number,
frameTo: number,
): ThunkAction {
return async (dispatch: ActionCreator<Dispatch>): Promise<void> => {
try {
const frame = await sessionInstance.annotations.searchEmpty(frameFrom, frameTo);
if (frame !== null) {
dispatch(changeFrameAsync(frame));
}
} catch (error) {
dispatch({
type: AnnotationActionTypes.SEARCH_EMPTY_FRAME_FAILED,
payload: {
error,
},
});
}
};
}

export function pasteShapeAsync(): ThunkAction {
return async (dispatch: ActionCreator<Dispatch>): Promise<void> => {
const {
Expand Down
3 changes: 3 additions & 0 deletions cvat-ui/src/assets/next-empty-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions cvat-ui/src/assets/next-filtered-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions cvat-ui/src/assets/previous-empty-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions cvat-ui/src/assets/previous-filtered-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions cvat-ui/src/components/annotation-page/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -300,3 +300,20 @@
}
}
}

.cvat-player-previous-inlined-button,
.cvat-player-next-inlined-button,
.cvat-player-previous-filtered-inlined-button,
.cvat-player-next-filtered-inlined-button,
.cvat-player-previous-empty-inlined-button,
.cvat-player-next-empty-inlined-button {
color: $player-buttons-color;

&:not(:first-child) {
margin-left: 12px;
}

> svg {
transform: scale(1.8);
}
}
Loading

0 comments on commit 990f61d

Please sign in to comment.