Skip to content

Commit

Permalink
feat(pointcloud): Support Unifying Params
Browse files Browse the repository at this point in the history
  • Loading branch information
Kerwin-L committed Dec 1, 2022
1 parent 11e39d7 commit 8079b42
Show file tree
Hide file tree
Showing 18 changed files with 559 additions and 35 deletions.
2 changes: 1 addition & 1 deletion packages/lb-annotation/src/core/pointCloud/annotation.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* @file Unified management of pointCloud & pointCloud2dOperation (Three views => Top & Side & Back)
* @file Unify management of pointCloud & pointCloud2dOperation (Three views => Top & Side & Back)
* @createDate 2022-07-18
* @author Ron <[email protected]>
*/
Expand Down
2 changes: 2 additions & 0 deletions packages/lb-components/docs/annotation.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ enum ESubmitType {
Save = 7, // 点击保存
BatchUpdateTrackID = 8, // 批量更改 TrackID (PointCloud)
SyncImgList = 10001, // 仅更改数据
SyncCurrentPageData = 10002, // 同步当页数据
}

// 结果类型
Expand Down Expand Up @@ -519,6 +520,7 @@ enum ESubmitType {
Save = 7, // 点击保存
BatchUpdateTrackID = 8, // 批量更改 TrackID (PointCloud)
SyncImgList = 10001, // 仅更改数据
SyncCurrentPageData = 10002, // 同步当页数据
}


Expand Down
1 change: 1 addition & 0 deletions packages/lb-components/docs/annotation_en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ enum ESubmitType {
Save = 7,
BatchUpdateTrackID = 8,
SyncImgList = 10001,
SyncCurrentPageData = 10002, // 同步当页数据
}

interface IFileItem {
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,267 @@
import { ESubmitType } from '@/constant';
import { BatchUpdateResultByTrackID, ToSubmitFileData } from '@/store/annotation/actionCreators';
import { LabelBeeContext, useDispatch } from '@/store/ctx';
import { Form, InputNumber, message, Modal, Popover, Select } from 'antd';
import React, { useCallback, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { QuestionCircleOutlined } from '@ant-design/icons';
import { IPointCloudConfig, PointCloudUtils } from '@labelbee/lb-utils';
import { connect } from 'react-redux';
import { AppState } from '@/store';
import { AnnotationFileList } from '@/types/data';
import { useSingleBox } from '../../hooks/useSingleBox';
import { MathUtils } from '@labelbee/lb-annotation';

interface IProps {
id?: number;
visible: boolean;
onCancel: () => void;
config: IPointCloudConfig;
imgList: AnnotationFileList;
imgIndex: number;
}

const layout = {
labelCol: { span: 8 },
wrapperCol: { span: 16 },
};

const defaultNumberRules = [{ required: true, message: '请填写一个数字' }];
const defaultSelectedAttribute = [{ required: true, message: '请选择主属性' }];
const DECIMAL_PLACES = 2;

const PrefixTag: React.FC<{ text: string }> = ({ text }) => {
return (
<span
style={{
borderRadius: '4px 0px 0px 4px',
padding: '0px 12px',
background: '#FAFAFA',
border: '1px solid rgb(217 217 217)',
borderRight: '0',
display: 'flex',
alignItems: 'center',
height: 32,
}}
>
{text}
</span>
);
};

const UnifyParamsModal = ({ id, visible, onCancel, config, imgList, imgIndex }: IProps) => {
const dispatch = useDispatch();
const { selectedBox } = useSingleBox();
const [size, setSize] = useState<{ width: number; height: number; depth: number }>();

const [form] = Form.useForm();
const { t } = useTranslation();

useEffect(() => {
if (visible === false) {
// Clear All Data
form.resetFields();
setSize(undefined);
}
}, [visible]);

const onFinish = (values: any) => {
if (!id) {
return;
}

if (!size) {
message.info('该范围不存在更改数据, 请更改统一范围');
return;
}

dispatch(ToSubmitFileData(ESubmitType.SyncImgList));
const newData = {
attribute: values.attribute,
};

if (config.secondaryAttributeConfigurable) {
const newSubAttribute = {};
config.inputList?.forEach((data) => {
const subData = values[data.value];
if (subData !== undefined) {
Object.assign(newSubAttribute, { [data.value]: subData });
}
});

if (Object.keys(newSubAttribute).length > 0) {
Object.assign(newData, { subAttribute: newSubAttribute });
}
}

if (size) {
Object.assign(newData, size);
}

dispatch(BatchUpdateResultByTrackID(id, newData, [values.prevPage - 1, values.nextPage - 1]));
onCancel();
};

const recalculateSize = useCallback(() => {
const { prevPage, nextPage } = form.getFieldsValue(['prevPage', 'nextPage']);

// 1. Filter the imgInfo in range.
const newImgList = imgList.filter((_, i) =>
MathUtils.isInRange(i, [prevPage - 1, nextPage - 1]),
);

if (
!(newImgList?.length > 0) ||
!selectedBox?.info ||
selectedBox?.info?.trackID === undefined
) {
setSize(undefined);
return;
}

// 2. Get the Max Size of imgList
const newMaxSize = PointCloudUtils.getMaxSizeFromBox({
trackID: selectedBox.info.trackID,
imgList: newImgList as Array<{ result: string }>,
});

setSize(newMaxSize);
}, [imgList, selectedBox, imgIndex]);

const onOk = () => form.submit();

const sizeShow = () => {
if (!size || !selectedBox?.info) {
return;
}
const style = { marginRight: 16 };

const { length, width, height } = PointCloudUtils.transferBox2Kitti({
...selectedBox?.info, // Just for the type check
...size,
});

return (
<div>
<span style={style}>
{t('Length')}: {length.toFixed(DECIMAL_PLACES)}
</span>
<span style={style}>
{t('Width')}: {width.toFixed(DECIMAL_PLACES)}
</span>
<span style={style}>
{t('Height')}: {height.toFixed(DECIMAL_PLACES)}
</span>
<Popover placement='rightBottom' content='统一尺寸为该ID的所有标注框中最大的尺寸'>
<QuestionCircleOutlined />
</Popover>
</div>
);
};
const selectStyle = {
width: '200px',
};

const attributeStyle = {
marginBottom: '24px',
display: 'flex',
alignItems: 'center',
};

return (
<Modal
title={t('UnifyParams')}
visible={visible}
onCancel={onCancel}
onOk={onOk}
wrapClassName='labelbee-custom-modal'
>
<Form {...layout} form={form} onFinish={onFinish}>
<Form.Item name='id' label={t('CurrentBoxTrackIDs')}>
{id}
</Form.Item>

<Form.Item label={t('UnifyTrackIDRange')} required={true}>
<Form.Item
style={{ display: 'inline-block' }}
rules={defaultNumberRules}
name='prevPage'
noStyle={true}
>
<InputNumber min={1} style={{ width: '80px' }} onChange={() => recalculateSize()} />
</Form.Item>
<span
style={{
display: 'inline-block',
width: '24px',
textAlign: 'center',
}}
>
-
</span>
<Form.Item
style={{ display: 'inline-block' }}
rules={defaultNumberRules}
name='nextPage'
noStyle={true}
>
<InputNumber min={1} style={{ width: '80px' }} onChange={() => recalculateSize()} />
</Form.Item>
<span
style={{
display: 'inline-block',
width: '40x',
marginLeft: '10px',
textAlign: 'center',
}}
>
{t('Page')}
</span>
</Form.Item>

<Form.Item name='UnifySize' label={t('UnifySize')}>
{sizeShow()}
</Form.Item>

<Form.Item label={t('UnifyTag')} required={true}>
<div style={attributeStyle}>
<PrefixTag text={t('Attribute')} />
<Form.Item name='attribute' noStyle={true} rules={defaultSelectedAttribute}>
<Select style={selectStyle}>
{config.attributeList.map((v) => (
<Select.Option key={v.value} value={v.value}>
{v.key}
</Select.Option>
))}
</Select>
</Form.Item>
</div>
{config.secondaryAttributeConfigurable &&
config.inputList.map((v) => (
<div key={v.value} style={attributeStyle}>
<PrefixTag text={v.key} />
<Form.Item name={v.value} noStyle={true} required={false}>
<Select style={selectStyle}>
{v.subSelected?.map((subData) => (
<Select.Option key={subData.value} value={subData.value}>
{subData.key}
</Select.Option>
))}
</Select>
</Form.Item>
</div>
))}
</Form.Item>
</Form>
</Modal>
);
};

const mapStateToProps = (state: AppState) => {
return {
imgList: state.annotation.imgList,
imgIndex: state.annotation.imgIndex,
};
};

export default connect(mapStateToProps, null, null, { context: LabelBeeContext })(UnifyParamsModal);
1 change: 1 addition & 0 deletions packages/lb-components/src/constant/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export enum ESubmitType {
Save = 7, // 点击保存
BatchUpdateTrackID = 8, // 批量更改 TrackID (PointCloud)
SyncImgList = 10001, // 仅更改数据
SyncCurrentPageData = 10002, // 同步当页数据
}
// css 命名前缀
export const prefix = 'bee';
Expand Down
2 changes: 2 additions & 0 deletions packages/lb-components/src/store/Actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ export const ANNOTATION_ACTIONS = {
UPDATE_ANNOTATION_VALID: '@@UPDATE_ANNOTATION_VALID',

BATCH_UPDATE_TRACK_ID: '@@BATCH_UPDATE_TRACK_ID',

BATCH_UPDATE_RESULT_BY_TRACK_ID: '@@BATCH_UPDATE_RESULT_BY_TRACK_ID'
};

export const IMAGE_ATTRIBUTE_ACTIONS = {
Expand Down
17 changes: 17 additions & 0 deletions packages/lb-components/src/store/annotation/actionCreators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { ESubmitType } from '@/constant';
import { EPageTurningOperation } from '@/data/enums/AnnotationSize';
import PageOperator from '@/utils/PageOperator';
import { jsonParser } from '@/utils';
import { IPointCloudBox } from '@labelbee/lb-utils';

const dispatchTasks = (dispatch: any, tasks: any[]) => tasks.map((task) => dispatch(task));

Expand Down Expand Up @@ -214,6 +215,22 @@ export function BatchUpdateTrackID(
};
}


export function BatchUpdateResultByTrackID(
id: number, // originData
newData: Partial<IPointCloudBox>,
rangeIndex: [number, number],
): AnnotationActionTypes {
return {
type: ANNOTATION_ACTIONS.BATCH_UPDATE_RESULT_BY_TRACK_ID,
payload: {
id,
newData,
rangeIndex,
},
};
}

/**
* 初始化任务数据
* @param param0
Expand Down
24 changes: 24 additions & 0 deletions packages/lb-components/src/store/annotation/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,30 @@ export const annotationReducer = (
};
}

case ANNOTATION_ACTIONS.BATCH_UPDATE_RESULT_BY_TRACK_ID: {
const { id, newData, rangeIndex } = action.payload;
const { imgList, imgIndex, onSubmit } = state;
const newImgList = imgList.map((v, i) => {
if (MathUtils.isInRange(i, rangeIndex)) {
return {
...v,
result: PointCloudUtils.batchUpdateResultByTrackID({ id, newData, result: v.result }),
};
}
return v;
});

// Notify external data changes.
if (onSubmit) {
onSubmit([newImgList[imgIndex]], ESubmitType.BatchUpdateTrackID, imgIndex, newImgList);
}

return {
...state,
imgList: newImgList,
};
}

// eslint-disable-next-line no-fallthrough
default:
return state;
Expand Down
Loading

0 comments on commit 8079b42

Please sign in to comment.