박선진

1. 응답으로 디텍션=true 받은 경우 해당 프레임 데이터를 이미지로 저장

2. save image api 추가(방문자 사진 업로드 기능)
......@@ -4,8 +4,6 @@ const ffmpeg = require('ffmpeg');
const request = require('request')
const router = express.Router();
const path = require('path');
//================================================================
router.post('/videoResult', function (req, res) {
......@@ -15,7 +13,6 @@ router.post('/videoResult', function (req, res) {
str = preview.replace(/^data:(.*?);base64,/, "");
str = str.replace(/ /g, '+');
fs.writeFileSync(`./data/temp.mp4`, str, 'base64', function (err) {
if (err) throw err;
console.log("video saved");
......@@ -24,8 +21,6 @@ router.post('/videoResult', function (req, res) {
let process = new ffmpeg(`./data/temp.mp4`);
detectedImgFile = "test.jpg"; // null로 바꿀 것
process.then(function (video) {
video.fnExtractFrameToJPG(__dirname + "/data",
{
......@@ -33,31 +28,26 @@ router.post('/videoResult', function (req, res) {
file_name: 'frame_%s'
}, function (error, files) {
if (!error)
console.log('###1 Frames =>' + files);
console.log("###2 갯수 => " + files.length)
console.log("###3 첫번째 파일 => " + files[0]); // 마지막 파일은 영상임
let base64str = base64_encode(files[0]);
console.log("###4 base64str => " + base64str);
console.log("##### for")
for(var i=0;i<files.length-1;i++){
let base64str = base64_encode(files[i]);
request.post({
url: 'http://101.101.210.73/process',
form: {
'data': base64_encode(files[0])
'data': base64str,
'index': i
},
json: true
}, (err, response, body) => {
console.log(body)
var index=body['index'];
if(body['unknown_person'] == true){
save_Result_image((files[index]), 'unknown', index);
}
if(body['fire_broken'] == true){
save_Result_image((files[index]), 'fire', index);
}
})
}
/**
* TODO
* 반복문돌면서 각 프레임 파이썬 api 요청하고 응답받아서
* 하나라도 true나오면 프론트에 감지된 이미지파일주소 응답
*/
detectedImgFile=null;
}
)
})
......@@ -66,7 +56,28 @@ router.post('/videoResult', function (req, res) {
console.error(err);
}
return res.json({ data: detectedImgFile });
return res.json({ data: true });
});
router.post('/saveImage', function (req, res) {
try {
let preview = req.body[0].preview;
str = preview.replace(/^data:(.*?);base64,/, "");
base64str = str.replace(/ /g, '+');
request.post({
url: 'http://101.101.210.73/save',
form: {
'data': base64str,
'name': 'temp'
},
json: true
}, (err, response, body) => {
console.log(body);
})
} catch (err) {
console.error(err);
}
return res.json({ data: true });
});
function base64_encode(file) {
......@@ -76,4 +87,12 @@ function base64_encode(file) {
return new Buffer(bitmap).toString('base64');
}
function save_Result_image(file, type, index){
var bitmap = fs.readFileSync(file);
var filePath = './' + type + '/' + index + '.jpg';
fs.writeFile(filePath, bitmap, function(err){
console.log('save');
});
}
module.exports = router;
\ No newline at end of file
......
No preview for this file type
......@@ -4,11 +4,31 @@
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@types/concat-stream": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/@types/concat-stream/-/concat-stream-1.6.0.tgz",
"integrity": "sha1-OU2+C7X+5Gs42JZzXoto7yOQ0A0=",
"requires": {
"@types/node": "*"
}
},
"@types/form-data": {
"version": "0.0.33",
"resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-0.0.33.tgz",
"integrity": "sha1-yayFsqX9GENbjIXZ7LUObWyJP/g=",
"requires": {
"@types/node": "*"
}
},
"@types/node": {
"version": "14.0.14",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.14.tgz",
"integrity": "sha512-syUgf67ZQpaJj01/tRTknkMNoBBLWJOBODF0Zm4NrXmiSuxjymFrxnTu1QVYRubhVkRcZLYZG8STTwJRdVm/WQ==",
"optional": true
"integrity": "sha512-syUgf67ZQpaJj01/tRTknkMNoBBLWJOBODF0Zm4NrXmiSuxjymFrxnTu1QVYRubhVkRcZLYZG8STTwJRdVm/WQ=="
},
"@types/qs": {
"version": "6.9.3",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.3.tgz",
"integrity": "sha512-7s9EQWupR1fTc2pSMtXRQ9w9gLOcrJn+h7HOXw4evxyvVqMi4f+q7d2tnFe3ng3SNHjtK+0EzGMGFUQX4/AQRA=="
},
"accepts": {
"version": "1.3.7",
......@@ -54,6 +74,11 @@
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
},
"asap": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
"integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY="
},
"asn1": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
......@@ -107,6 +132,11 @@
"type-is": "~1.6.17"
}
},
"buffer-from": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
},
"bytes": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
......@@ -130,6 +160,17 @@
"delayed-stream": "~1.0.0"
}
},
"concat-stream": {
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
"integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
"requires": {
"buffer-from": "^1.0.0",
"inherits": "^2.0.3",
"readable-stream": "^2.2.2",
"typedarray": "^0.0.6"
}
},
"console-control-strings": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
......@@ -341,6 +382,11 @@
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
},
"fs": {
"version": "0.0.1-security",
"resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz",
"integrity": "sha1-invTcYa23d84E/I4WLV+yq9eQdQ="
},
"gauge": {
"version": "2.7.4",
"resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
......@@ -356,6 +402,11 @@
"wide-align": "^1.1.0"
}
},
"get-port": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz",
"integrity": "sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw="
},
"getpass": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
......@@ -383,6 +434,17 @@
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
"integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk="
},
"http-basic": {
"version": "8.1.3",
"resolved": "https://registry.npmjs.org/http-basic/-/http-basic-8.1.3.tgz",
"integrity": "sha512-/EcDMwJZh3mABI2NhGfHOGOeOZITqfkEO4p/xK+l3NpyncIHUQBoMvCSF/b5GqvKtySC2srL/GGG3+EtlqlmCw==",
"requires": {
"caseless": "^0.12.0",
"concat-stream": "^1.6.2",
"http-response-object": "^3.0.1",
"parse-cache-control": "^1.0.1"
}
},
"http-errors": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
......@@ -395,6 +457,21 @@
"toidentifier": "1.0.0"
}
},
"http-response-object": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/http-response-object/-/http-response-object-3.0.2.tgz",
"integrity": "sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA==",
"requires": {
"@types/node": "^10.0.3"
},
"dependencies": {
"@types/node": {
"version": "10.17.26",
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.26.tgz",
"integrity": "sha512-myMwkO2Cr82kirHY8uknNRHEVtn0wV3DTQfkrjx17jmkstDRZ24gNUdl8AHXVyVclTYI/bNjgTPTAWvWLqXqkw=="
}
}
},
"http-signature": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
......@@ -533,6 +610,11 @@
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
},
"node-fetch": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
"integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA=="
},
"npmlog": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
......@@ -587,6 +669,11 @@
"opencv-build": "^0.1.9"
}
},
"parse-cache-control": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz",
"integrity": "sha1-juqz5U+laSD+Fro493+iGqzC104="
},
"parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
......@@ -621,6 +708,14 @@
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
},
"promise": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/promise/-/promise-8.1.0.tgz",
"integrity": "sha512-W04AqnILOL/sPRXziNicCjSNRruLAuIHEOVBazepu0545DDNGYHz7ar9ZgZ1fMU8/MA4mVxp5rkBWRi6OXIy3Q==",
"requires": {
"asap": "~2.0.6"
}
},
"proxy-addr": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz",
......@@ -819,6 +914,49 @@
"ansi-regex": "^2.0.0"
}
},
"sync-request": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/sync-request/-/sync-request-6.1.0.tgz",
"integrity": "sha512-8fjNkrNlNCrVc/av+Jn+xxqfCjYaBoHqCsDz6mt030UMxJGr+GSfCV1dQt2gRtlL63+VPidwDVLr7V2OcTSdRw==",
"requires": {
"http-response-object": "^3.0.1",
"sync-rpc": "^1.2.1",
"then-request": "^6.0.0"
}
},
"sync-rpc": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/sync-rpc/-/sync-rpc-1.3.6.tgz",
"integrity": "sha512-J8jTXuZzRlvU7HemDgHi3pGnh/rkoqR/OZSjhTyyZrEkkYQbk7Z33AXp37mkPfPpfdOuj7Ex3H/TJM1z48uPQw==",
"requires": {
"get-port": "^3.1.0"
}
},
"then-request": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/then-request/-/then-request-6.0.2.tgz",
"integrity": "sha512-3ZBiG7JvP3wbDzA9iNY5zJQcHL4jn/0BWtXIkagfz7QgOL/LqjCEOBQuJNZfu0XYnv5JhKh+cDxCPM4ILrqruA==",
"requires": {
"@types/concat-stream": "^1.6.0",
"@types/form-data": "0.0.33",
"@types/node": "^8.0.0",
"@types/qs": "^6.2.31",
"caseless": "~0.12.0",
"concat-stream": "^1.6.0",
"form-data": "^2.2.0",
"http-basic": "^8.1.1",
"http-response-object": "^3.0.1",
"promise": "^8.0.0",
"qs": "^6.4.0"
},
"dependencies": {
"@types/node": {
"version": "8.10.61",
"resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.61.tgz",
"integrity": "sha512-l+zSbvT8TPRaCxL1l9cwHCb0tSqGAGcjPJFItGGYat5oCTiq1uQQKYg5m7AF1mgnEBzFXGLJ2LRmNjtreRX76Q=="
}
}
},
"toidentifier": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
......@@ -855,6 +993,11 @@
"mime-types": "~2.1.24"
}
},
"typedarray": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
},
"unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
......
......@@ -14,8 +14,11 @@
"cors": "^2.8.5",
"express": "^4.17.1",
"ffmpeg": "0.0.4",
"fs": "0.0.1-security",
"node-fetch": "^2.6.0",
"opencv4nodejs": "^5.6.0",
"path": "^0.12.7",
"request": "^2.88.2"
"request": "^2.88.2",
"sync-request": "^6.1.0"
}
}
......
......@@ -12,5 +12,5 @@ app.use(bodyParser.urlencoded({limit: '100mb', extended: true}));
app.use(bodyParser());
app.use('/api', api);
const port = 3003;
const port = 3004;
app.listen(port, () => console.log(`노드서버 시작 : ${port}`));
......
import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { Switch, Route, withRouter, Redirect } from 'react-router';
import { Switch, Route, withRouter } from 'react-router';
import { TransitionGroup, CSSTransition } from 'react-transition-group';
import Hammer from 'rc-hammerjs';
......
......@@ -7,7 +7,6 @@ import {
Button,
Form,
FormGroup,
Label,
} from 'reactstrap';
class Subject extends PureComponent {
......@@ -36,12 +35,24 @@ class Subject extends PureComponent {
onClickSaveImage(e) {
e.preventDefault();
console.log(this.state.imageFiles);
console.log("save image");
this.setState({
imageFiles:[],
});
// post request
fetch('http://localhost:3004/api/saveImage',{
method: 'POST',
mode: 'cors',
cache: 'no-cache',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json',
},
redirect: 'follow',
referrer: 'no-referrer',
body: JSON.stringify(this.state.imageFiles)
})
.then(res=>res.json())
.then(data=>this.setState({videoAnalysisResult:data}))
console.log(this.state.videoAnalysisResult);
}
render() {
......@@ -66,7 +77,7 @@ class Subject extends PureComponent {
/>
{this.state.imageFiles.length > 0 ? <div>
{this.state.imageFiles.map((file, idx) => (
<img alt="..." src={file.preview} key={`img-id-${idx.toString()}`} />))}
<img style={{height: '200px'}}alt="..." src={file.preview} key={`img-id-${idx.toString()}`} />))}
</div> : <img
alt="..."
src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxOTEiIGhlaWdodD0iMTQxIj48cmVjdCB3aWR0aD0iMTkxIiBoZWlnaHQ9IjE0MSIgZmlsbD0iI2VlZSIvPjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9Ijk1LjUiIHk9IjcwLjUiIHN0eWxlPSJmaWxsOiNhYWE7Zm9udC13ZWlnaHQ6Ym9sZDtmb250LXNpemU6MTJweDtmb250LWZhbWlseTpBcmlhbCxIZWx2ZXRpY2Esc2Fucy1zZXJpZjtkb21pbmFudC1iYXNlbGluZTpjZW50cmFsIj4xOTF4MTQxPC90ZXh0Pjwvc3ZnPg=="
......
......@@ -10,6 +10,8 @@ import {
} from 'reactstrap';
import Widget from '../../components/Widget/Widget';
var fireResultImages=[];
var unknownResultImages=[];
class Dashboard extends React.Component {
constructor(props) {
......@@ -19,9 +21,13 @@ class Dashboard extends React.Component {
// this.analysisVideo = this.analysisVideo.bind(this);
this.state = {
videoFiles: [],
videoAnalysisResult:null
videoAnalysisResult:null,
};
}
importAll(r){
return r.keys().map(r);
}
onChangeInputVideo(e) {
const files = [];
......@@ -39,11 +45,9 @@ class Dashboard extends React.Component {
onClickSaveVideo(e) {
e.preventDefault();
console.log(this.state.videoFiles);
console.log("upload video");
// post request
fetch('http://localhost:3002/api/videoResult',{
fetch('http://localhost:3004/api/videoResult',{
method: 'POST',
mode: 'cors',
cache: 'no-cache',
......@@ -66,9 +70,13 @@ class Dashboard extends React.Component {
performance: PropTypes.any,
};
componentWillMount(){
fireResultImages= this.importAll(require.context('../../../../Back-end/fire/', false, /\.(png|jpg|svg)$/))
unknownResultImages= this.importAll(require.context('../../../../Back-end/unknown/', false, /\.(png|jpg|svg)$/))
}
render() {
console.log("render")
console.log(this.state.videoFiles)
console.log(this.state.videoAnalysisResult);
return (
<div>
<h1 className="page-title">Video Analysis <small><small>Performance</small></small></h1>
......@@ -100,9 +108,20 @@ class Dashboard extends React.Component {
title={<h5><span className="fw-semi-bold">Results</span></h5>}
>
<div>
<div className="text-center" style={{ height: '300px' }} />
<p className="fs-mini text-muted">
{fireResultImages.length > 0 ? <div>
<p className="fw-semi-bold"> 불났어요!!
</p>
{fireResultImages.map(
(image, index) => <img style={{height: '200px', margin: '10px 10px 10px 10px'}}alt="..." key={index} src={image}/>)}
</div> : <div/>}
</div>
<div>
{unknownResultImages.length > 0 ? <div>
<p className="fw-semi-bold"> 침입자 발생!!
</p>
{unknownResultImages.map(
(image, index) => <img style={{height: '200px', margin: '10px 10px 10px 10px'}}alt="..." key={index} src={image}/>)}
</div> : <div/>}
</div>
</Widget>
</Col>
......@@ -118,23 +137,4 @@ function mapStateToProps(state) {
}
}
export default connect(mapStateToProps)(Dashboard);
function postData(url = '', data = {}) {
// Default options are marked with *
return fetch(url, {
method: 'POST', // *GET, POST, PUT, DELETE, etc.
mode: 'cors', // no-cors, cors, *same-origin
cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
credentials: 'same-origin', // include, *same-origin, omit
headers: {
'Content-Type': 'application/json',
// 'Content-Type': 'application/x-www-form-urlencoded',
},
redirect: 'follow', // manual, *follow, error
referrer: 'no-referrer', // no-referrer, *client
body: JSON.stringify(data), // body data type must match "Content-Type" header
})
.then(response => response.json()); // parses JSON response into native JavaScript objects
}
\ No newline at end of file
export default connect(mapStateToProps)(Dashboard);
\ No newline at end of file
......