Skip to content

Commit

Permalink
happy path works
Browse files Browse the repository at this point in the history
  • Loading branch information
SkalskiP committed Sep 27, 2022
1 parent aa7bf80 commit c5b480e
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 44 deletions.
18 changes: 12 additions & 6 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,14 @@ import NotificationsView from './views/NotificationsView/NotificationsView';
interface IProps {
projectType: ProjectType;
windowSize: ISize;
ObjectDetectorLoaded: boolean;
PoseDetectionLoaded: boolean;
objectDetectorLoaded: boolean;
poseDetectionLoaded: boolean;
roboflowJSObjectDetectorLoaded: boolean;
}

const App: React.FC<IProps> = ({projectType, windowSize, ObjectDetectorLoaded, PoseDetectionLoaded}) => {
const App: React.FC<IProps> = (
{projectType, windowSize, objectDetectorLoaded, poseDetectionLoaded, roboflowJSObjectDetectorLoaded}
) => {
const selectRoute = () => {
if (!!PlatformModel.mobileDeviceData.manufacturer && !!PlatformModel.mobileDeviceData.os)
return <MobileMainView/>;
Expand All @@ -36,8 +39,10 @@ const App: React.FC<IProps> = ({projectType, windowSize, ObjectDetectorLoaded, P
}
};

const isAILoaded = objectDetectorLoaded || poseDetectionLoaded || roboflowJSObjectDetectorLoaded

return (
<div className={classNames('App', {'AI': ObjectDetectorLoaded || PoseDetectionLoaded})}
<div className={classNames('App', {'AI': isAILoaded})}
draggable={false}
>
{selectRoute()}
Expand All @@ -50,8 +55,9 @@ const App: React.FC<IProps> = ({projectType, windowSize, ObjectDetectorLoaded, P
const mapStateToProps = (state: AppState) => ({
projectType: state.general.projectData.type,
windowSize: state.general.windowSize,
ObjectDetectorLoaded: state.ai.isObjectDetectorLoaded,
PoseDetectionLoaded: state.ai.isPoseDetectorLoaded
objectDetectorLoaded: state.ai.isObjectDetectorLoaded,
poseDetectionLoaded: state.ai.isPoseDetectorLoaded,
roboflowJSObjectDetectorLoaded: state.ai.isRoboflowJSObjectDetectorLoaded
});

export default connect(
Expand Down
19 changes: 16 additions & 3 deletions src/ai/RoboflowObjectDetector.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as express from 'roboflow';
// import * as express from 'roboflow';
import {max} from "lodash";


export interface DetectedObject {
Expand Down Expand Up @@ -36,9 +37,21 @@ export class RoboflowObjectDetector {

RoboflowObjectDetector.model
.detect(image)
.then((predictions: DetectedObject[]) => {
.then((predictions) => {
const processedPredictions: DetectedObject[] = predictions.map((raw) => {
return {
bbox: [
max([raw.bbox.x - raw.bbox.width / 2, 0]),
max([raw.bbox.y - raw.bbox.height / 2, 0]),
raw.bbox.width,
raw.bbox.height
],
class: raw.class,
score: raw.confidence
}
})
if (callback) {
callback(predictions)
callback(processedPredictions)
}
})
.catch((error) => {
Expand Down
43 changes: 29 additions & 14 deletions src/logic/actions/AIObjectDetectionActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {PopupWindowType} from '../../data/enums/PopupWindowType';
import {updateActivePopupType} from '../../store/general/actionCreators';
import {AISelector} from '../../store/selectors/AISelector';
import {AIActions} from './AIActions';
import {RoboflowObjectDetector} from '../../ai/RoboflowObjectDetector';

export class AIObjectDetectionActions {
public static detectRectsForActiveImage(): void {
Expand All @@ -21,22 +22,36 @@ export class AIObjectDetectionActions {
}

public static detectRects(imageId: string, image: HTMLImageElement): void {
if (LabelsSelector.getImageDataById(imageId).isVisitedByObjectDetector || !AISelector.isAIObjectDetectorModelLoaded())
if (LabelsSelector.getImageDataById(imageId).isVisitedByObjectDetector)
return;

store.dispatch(updateActivePopupType(PopupWindowType.LOADER));
ObjectDetector.predict(image, (predictions: DetectedObject[]) => {
const suggestedLabelNames = AIObjectDetectionActions.extractNewSuggestedLabelNames(LabelsSelector.getLabelNames(), predictions);
const rejectedLabelNames = AISelector.getRejectedSuggestedLabelList();
const newlySuggestedNames = AIActions.excludeRejectedLabelNames(suggestedLabelNames, rejectedLabelNames);
if (newlySuggestedNames.length > 0) {
store.dispatch(updateSuggestedLabelList(newlySuggestedNames));
store.dispatch(updateActivePopupType(PopupWindowType.SUGGEST_LABEL_NAMES));
} else {
store.dispatch(updateActivePopupType(null));
}
AIObjectDetectionActions.saveRectPredictions(imageId, predictions);
})
if (AISelector.isAIObjectDetectorModelLoaded()) {
store.dispatch(updateActivePopupType(PopupWindowType.LOADER));
ObjectDetector.predict(image, (predictions: DetectedObject[]) => {
AIObjectDetectionActions.handleObjectDetectorResults(imageId, predictions);
})
}

if (AISelector.isAIRoboflowJSObjectDetectorModelLoaded()) {
store.dispatch(updateActivePopupType(PopupWindowType.LOADER));
RoboflowObjectDetector.predict(image, (predictions: DetectedObject[]) => {
AIObjectDetectionActions.handleObjectDetectorResults(imageId, predictions);
})
}
}

private static handleObjectDetectorResults = (imageId: string, predictions: DetectedObject[]) => {
const suggestedLabelNames = AIObjectDetectionActions
.extractNewSuggestedLabelNames(LabelsSelector.getLabelNames(), predictions);
const rejectedLabelNames = AISelector.getRejectedSuggestedLabelList();
const newlySuggestedNames = AIActions.excludeRejectedLabelNames(suggestedLabelNames, rejectedLabelNames);
if (newlySuggestedNames.length > 0) {
store.dispatch(updateSuggestedLabelList(newlySuggestedNames));
store.dispatch(updateActivePopupType(PopupWindowType.SUGGEST_LABEL_NAMES));
} else {
store.dispatch(updateActivePopupType(null));
}
AIObjectDetectionActions.saveRectPredictions(imageId, predictions);
}

public static saveRectPredictions(imageId: string, predictions: DetectedObject[]) {
Expand Down
24 changes: 10 additions & 14 deletions src/logic/initializer/AppInitializer.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import {updateWindowSize} from "../../store/general/actionCreators";
import {ContextManager} from "../context/ContextManager";
import {store} from "../../index";
import {PlatformUtil} from "../../utils/PlatformUtil";
import {PlatformModel} from "../../staticModels/PlatformModel";
import {EventType} from "../../data/enums/EventType";
import {GeneralSelector} from "../../store/selectors/GeneralSelector";
import {EnvironmentUtil} from "../../utils/EnvironmentUtil";
import {updateWindowSize} from '../../store/general/actionCreators';
import {ContextManager} from '../context/ContextManager';
import {store} from '../../index';
import {PlatformUtil} from '../../utils/PlatformUtil';
import {PlatformModel} from '../../staticModels/PlatformModel';
import {EventType} from '../../data/enums/EventType';
import {GeneralSelector} from '../../store/selectors/GeneralSelector';
import {EnvironmentUtil} from '../../utils/EnvironmentUtil';

export class AppInitializer {
public static inti():void {
Expand Down Expand Up @@ -37,11 +37,7 @@ export class AppInitializer {
};

private static disableUnwantedKeyBoardBehaviour = (event: KeyboardEvent) => {
if (PlatformModel.isMac && event.metaKey) {
event.preventDefault();
}

if (["=", "+", "-"].includes(event.key)) {
if (['=', '+', '-'].includes(event.key)) {
if (event.ctrlKey || (PlatformModel.isMac && event.metaKey)) {
event.preventDefault();
}
Expand All @@ -61,4 +57,4 @@ export class AppInitializer {
PlatformModel.isSafari = PlatformUtil.isSafari(userAgent);
PlatformModel.isFirefox = PlatformUtil.isFirefox(userAgent);
};
}
}
4 changes: 4 additions & 0 deletions src/store/selectors/AISelector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ export class AISelector {
return store.getState().ai.isObjectDetectorLoaded;
}

public static isAIRoboflowJSObjectDetectorModelLoaded(): boolean {
return store.getState().ai.isRoboflowJSObjectDetectorLoaded;
}

public static isAIPoseDetectorModelLoaded(): boolean {
return store.getState().ai.isPoseDetectorLoaded;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ const EditorTopNavigationBar: React.FC<IProps> = (
updateCrossHairVisibleStatusAction(!crossHairVisible);
};

const showAIButtons = (activeLabelType === LabelType.RECT && AISelector.isAIObjectDetectorModelLoaded()) ||
(activeLabelType === LabelType.RECT && AISelector.isAIRoboflowJSObjectDetectorModelLoaded()) ||
(activeLabelType === LabelType.POINT && AISelector.isAIPoseDetectorModelLoaded())

return (
<div className={getClassName()}>
<div className='ButtonWrapper'>
Expand Down Expand Up @@ -174,8 +178,7 @@ const EditorTopNavigationBar: React.FC<IProps> = (
)
}
</div>
{((activeLabelType === LabelType.RECT && AISelector.isAIObjectDetectorModelLoaded()) ||
(activeLabelType === LabelType.POINT && AISelector.isAIPoseDetectorModelLoaded())) && <div className='ButtonWrapper'>
{showAIButtons && <div className='ButtonWrapper'>
{
getButtonWithTooltip(
'accept-all',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,19 @@ import React, {useState} from 'react';
import './LoadRoboflowModelPopup.scss';
import {GenericYesNoPopup} from '../GenericYesNoPopup/GenericYesNoPopup';
import {PopupActions} from '../../../logic/actions/PopupActions';
import {updateActivePopupType} from '../../../store/general/actionCreators';
import {AppState} from '../../../store';
import {connect} from 'react-redux';
import {TextField} from '@mui/material';
import {styled} from '@mui/system';
import {Settings} from '../../../settings/Settings';
import {RoboflowObjectDetector} from '../../../ai/RoboflowObjectDetector';
import {updateActiveLabelType} from '../../../store/labels/actionCreators';
import {LabelsActionTypes} from '../../../store/labels/types';
import {LabelType} from '../../../data/enums/LabelType';
import {updateRoboflowJSObjectDetectorStatus} from '../../../store/ai/actionCreators';
import {AIActionTypes} from '../../../store/ai/types';
import {LabelsSelector} from '../../../store/selectors/LabelsSelector';
import {AIObjectDetectionActions} from '../../../logic/actions/AIObjectDetectionActions';

const StyledTextField = styled(TextField)({
'& .MuiInputBase-root': {
Expand All @@ -32,12 +38,25 @@ const StyledTextField = styled(TextField)({
});


const LoadRoboflowModelPopup: React.FC = () => {
interface IProps {
updateActiveLabelTypeAction: (activeLabelType: LabelType) => LabelsActionTypes,
updateRoboflowJSObjectDetectorStatusAction: (isRoboflowJSObjectDetectorLoaded: boolean) => AIActionTypes
}

const LoadRoboflowModelPopup: React.FC<IProps> = ({
updateActiveLabelTypeAction, updateRoboflowJSObjectDetectorStatusAction
}) => {
const [publishableKey, setPublishableKey] = useState('');
const [modelId, setModelId] = useState('');
const [modelVersion, setModelVersion] = useState(1);

const onModelLoadSuccess = () => {
updateRoboflowJSObjectDetectorStatusAction(true)
updateActiveLabelTypeAction(LabelType.RECT)
const activeLabelType: LabelType = LabelsSelector.getActiveLabelType();
if (activeLabelType === LabelType.RECT) {
AIObjectDetectionActions.detectRectsForActiveImage();
}
PopupActions.close();
}

Expand Down Expand Up @@ -69,7 +88,7 @@ const LoadRoboflowModelPopup: React.FC = () => {

<StyledTextField
variant='standard'
id={'key'}
id={'publishable-key'}
autoComplete={'off'}
autoFocus={true}
type={'password'}
Expand All @@ -85,7 +104,7 @@ const LoadRoboflowModelPopup: React.FC = () => {

<StyledTextField
variant='standard'
id={'key'}
id={'model-id'}
autoComplete={'off'}
autoFocus={false}
type={'text'}
Expand Down Expand Up @@ -116,7 +135,8 @@ const LoadRoboflowModelPopup: React.FC = () => {
}

const mapDispatchToProps = {
updateActivePopupTypeAction: updateActivePopupType,
updateRoboflowJSObjectDetectorStatusAction: updateRoboflowJSObjectDetectorStatus,
updateActiveLabelTypeAction: updateActiveLabelType,
};

const mapStateToProps = (state: AppState) => ({});
Expand Down

0 comments on commit c5b480e

Please sign in to comment.