TextProcessing.zip
0.01MB

 

구현할 기능: 필기체를 인식하여 찾아낸 후보 글자들을 입력받아서, 다음에 올 확률이 높은 글자들을 반환해주는 클래스를 작성한다. 기존 단어들을 검색에 특화된 자료구조로 저장한다.

 

중점을 둘 부분: 실시간으로 단어검색을 해야하므로 빠른 연산속도가 필요하다. 단어들이 앱에 저장되어야 하므로 메모리를 절약해야 한다.

 

사전지식:

1. TRIE 자료구조

2. JAVA 특징

-컬렉션 함수

-문자열 객체

-접근제어자

-직렬화

3. JSON 파일형식

 

 

진행과정:

1. 자료구조 선정

-바이그램/트라이 비교

-개발 목적 간단히 정의

 

2.선정된 자료구조 학습

-블로그,위키백과,서울대 발표자료,서강대 논문

 

3.핵심코드 구현 및 정확성 확인

-백준 문제 풀기

 

4.요구사항 정리 및 설계 

-입출력 포맷, 필요 함수, 기타 조건 정리

-시간복잡도, 공간복잡도

 

5.코딩 및 필요지식 학습

-Java 컬렉션 API 학습

-String, Stringbuilder 학습

-접근제어자 학습

-Serialize 학습

-추후 재설계하기 좋은지 확인

 

6.문제 발견 및 해결책 반영

-자료구조 변경(Map,음소별)

-데이터 삽입 및 오류 수정

 

7. 사용자화

-확률 적용

-사용방법 두 가지로 늘림

 

8.데이터 수집 및 테스트

-필요 데이터 파일 모으기

-데이터 전처리

-실행 및 결과확인

 

9.문서화 및 유지보수

-코드 정리, 주석 추가

-과정 정리 및 블로그 포스팅, 구조 시각화

 

 

'Project' 카테고리의 다른 글

[툰츄]  (0) 2019.11.06
[부귀영화-영화 추천 서비스]  (0) 2019.10.25
[WaterMelon-음원 사이트]  (0) 2019.10.25
[Hearable App-청각장애인용 스마트 앱]  (3) 2019.10.25
[MARK- 길건너기 2D 게임]  (0) 2019.10.25

1)한줄요약 : 멜론과 같은 음원 결제 및 다운로드 사이트를 제작

 

2)본인 역할 : 프로젝트리더.선행개발 및 본 개발로 MVC구조에 기반한 웹 서버 구조 설계 및 개발.

+선행개발: 검색 가능한 웹화면, 로그인,파일업로드 기능같이 부수적인 것들 미리 제작. Jsp와 BLOB 자료형 사용.

+팀원:ㄱㄱㅂ,ㅂㅊㅁ

 

3)본인이 사용한 스킬 : Java,Oracle Database,Spring,Jsp

+팀원스킬: JAVA,Oracle Database,Spring

 

4)힘들었던 점:  기술 이해의 불균형. 개발기간이 5일이어서 곧바로 분업했지만 수업에 완전히 참석하지 못한 팀원들이 이해에 어려움을 겪었다.

->2일이라도 스터디 제안,스터디에 가기 전 최대한 많은 내용을 공부하고 팀원의 이해를 도울 수 있는 자료를 만듬.

 

 

[주제를 정하기 위해서 SWOT 분석을 활용]

[구조도]

Main - 사용자가 원하는 기능을 선택하면 필요한 Controller의 메소드를 호출한다.

Controller - 각 기능에 필요한 서비스를 호출하고 관리한다.

Service

- UserServise : 사용자메뉴에 필요한 서비스를 포함한다.

- MusicService : 음원서비스에 필요한 서비스를 포함한다.

DAO

- UserRepository : 사용자 서비스에 필요한 insert,delete,find를 포함한다.

- MusicRepository : 음원 서비스에 필요한 insert,delete,find를 포함한다.

Database - 사용자데이터를 userdata에, 음원데이터를 musicdata에 저장한다.

 

[흐름도]

[본개발 시연 (DI구조를 선행개발과 합치지 못해서 콘솔창 구현)]

 

 

 

[주요 코드]

 

package com.watermelon.controller;

 

 

import org.springframework.context.support.AbstractApplicationContext;

import org.springframework.context.support.GenericXmlApplicationContext;

import org.springframework.jdbc.core.JdbcTemplate;

 

 

import com.watermelon.dao.IRepository;

 

 

public class RepositoryController {//   ICustomerService custService = new CustomerService();

       public IRepository repository;

       //AbstractApplicationContext context=new GenericXmlApplicationContext("application-config.xml");

       public RepositoryController(IRepository repository) {

          this.repository = repository;

       }   //원래는 여기서 서비스 선택해야됨

      

       public void run_insert() {

         repository.insert();

       }

}

 

package com.watermelon.dao;

public interface IRepository//같은 리포지터리로 많이 만들거니까 인터페이스

       void insert();

       void update();

       void print();

       void delete();

}

 

package com.watermelon.dao;

 

 

import java.util.Scanner;

 

 

import org.springframework.context.support.AbstractApplicationContext;

import org.springframework.context.support.GenericXmlApplicationContext;

import org.springframework.jdbc.core.JdbcTemplate;

import com.watermelon.model.Artist;

 

 

public class ArtistRepository implements IRepository//실체화된 리포지터리

    Scanner scan = new Scanner(System.in);

    //AbstractApplicationContext context = new GenericXmlApplicationContext("application-config.xml");

    JdbcTemplate jdbcTemplate;

    @Override

    public void insert() {

        System.out.print("번호 : ");

        int artist_num = scan.nextInt();

        System.out.print("이름 : ");

        String name = scan.next();

        System.out.print("날짜 : ");

        String create_date = scan.next();

        System.out.print("점수 : ");

        int score = scan.nextInt();

        Artist a = new Artist(artist_num, name, create_date, score);

        String sql = "insert into artist (artist_num, name, create_date, score)" + "values ('" + artist_num + "','"

                + name + "','" + create_date + "','" + score + "')";

        jdbcTemplate.update(sql);  //모델인 테이블에서 가져올거임

    }

    public void update() {

    }

    public void print() {

    }

    public void delete() {

    }

    public void setMethod(JdbcTemplate jdbcTemplate) {

        this.jdbcTemplate = jdbcTemplate;

    }

}

package com.watermelon.main;

 

 

import org.springframework.context.support.AbstractApplicationContext;

import org.springframework.context.support.GenericXmlApplicationContext;

import org.springframework.jdbc.core.JdbcTemplate;

 

 

import com.watermelon.dao.ArtistRepository;

 

 

public class WatermelonMain {

    public static void main(String[] arg) {

        AbstractApplicationContext context = new GenericXmlApplicationContext("application-config.xml");  //컨테이너 등록

        ArtistRepository a = context.getBean(ArtistRepository.class);  //컨테이너에선 손쉽게 생성하고 빈객체까지 취할수있음

        a.setMethod(context.getBean("jdbcTemplate",JdbcTemplate.class));  //jdbc도 빈객체로 설정되있을때 a빈객체에 넣어서 해당 과정 수행한다. 

        a.insert();  //사실 여기 메인에선 컨트롤러 만들어서 걔가 컨테이너 만들어서 위의 두줄 넣고 빈빼서 실행해야됐음

        }

}

 

<?xml version="1.0" encoding="UTF-8"?>

 

       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee  http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

       <!-- The definition of the Root Spring Container shared by all Servlets and  Filters -->

       <context-param>

              <param-name>contextConfigLocation</param-name>

              <param-value>/WEB-INF/spring/root-context.xml</param-value>

       </context-param>

       

       <!-- Creates the Spring Container shared by all Servlets and Filters -->

       <listener>

              <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

       </listener>

       <!-- Processes application requests -->

       <servlet>

              <servlet-name>appServlet</servlet-name>

              <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

              <init-param>

                     <param-name>contextConfigLocation</param-name>

                     <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>

              </init-param>

              <load-on-startup>1</load-on-startup>

       </servlet>

              

       <servlet-mapping>

              <servlet-name>appServlet</servlet-name>

              <url-pattern>/</url-pattern>

       </servlet-mapping>

</web-app>

 

//그리고 위처럼 음악파일도 똑같이 만들어서 뷰 파일로 결과 보내줘야함. jsp든 서블릿이든. 즉, 뷰와 컨트롤러 부분을 못만든 것이다.

 

 

 

[선행개발-논리적 데이터 모델]

 

 

 

[선행개발 시연]

 

 

[주요 코드]

 

메인 jsp

<%@ page language="java" contentType="text/html; charset=EUC-KR"

    pageEncoding="EUC-KR"%>

    <%@ page import="java.sql.*,javax.naming.*,javax.sql.*" %>

http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">

<title>Insert title here</title>

</head>

<body>

<script language='javascript'>

function wrong_input(){

       alert("잘못된 정보를 입력하셨습니다.");

       history.back();

}

function no_exist_result(){

       alert("원하시는 결과가 없습니다");

       history.back();

}

</script>

<%

       Context ctx = new InitialContext();

       DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/sec");

       Connection conn = ds.getConnection();

       String keyword = request.getParameter("keyword");

       

       if (keyword == null) {

              %><script>

              wrong_input();

              </script>

              <%

       }

       String sqlQuery = "select * from attachment where file_name='";

       sqlQuery +=keyword;

       sqlQuery += "'";

       System.out.println("SQL: "+sqlQuery);

       PreparedStatement ps =conn.prepareStatement(sqlQuery);

       ResultSet rs = ps.executeQuery();

       

       while(rs.next()){

              %>

              <tr> <li><td><a href="file_down.jsp?file_id=<%=rs.getInt("id")%>">

                   <td><%=rs.getString("file_name")%>

              

              </tr>

              <%

         }

         //예외처리 만들어줘야     

       conn.commit();

       rs.close();

       ps.close();

       conn.close();

       %>

</body>

</html>

 

파일업로드 jsp

<%@ page language="java" contentType="text/html; charset=EUC-KR"

    pageEncoding="utf-8"%>

    <%@ page import="java.sql.*,javax.naming.*,javax.sql.*" %>

<!DOCTYPE >

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">

<title>Upload files</title>

</head>

<body>

<script language='javascript'>

function wrong_input(){

       alert("로그인 하셔야죠!");

       window.location.href="login.html"; //history.back();

}

</script>

<%

String user_id=request.getParameter("user_id");

System.out.println(user_id);

if(user_id.equals("null"))

{%>

       

       <scripts>

       wrong_input();

       </scripts><%

}%>

    <div style="padding:5px; color:red;font-style:italic;">

       ${errorMessage}

    </div>

    

    <h2>Upload Files</h2>

    <form method="post" action="${pageContext.request.contextPath}/uploadToDB"

        enctype="multipart/form-data">

        

        Select file to upload:

        <br />

        <input type="file" name="file"  />

        <br />

        <input type="file" name="file" />

        <br />

        Description:

        <br />

        <input type="text" name="description" size="100" />

        <br />

        <br />

        <input type="submit" value="Upload" />

    </form>

</body>

</html>

 

 

클릭한 파일 다운로드

<%@ page language="java" contentType="text/html; charset=EUC-KR"

    pageEncoding="EUC-KR"%>

http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">

<title>Insert title here</title>

</head>

<body>

<%

String file_id=request.getParameter("file_id");

String str="http://localhost:8080/WaterMelon/downloadAttachment?id=";

str+=file_id;

System.out.println(str);

response.sendRedirect(str);

%>

<script>

              wrong_input();

</script>

</body>

</html>

 

BLOB 자료형으로 파일 클래스

import java.sql.Blob;

public class Attachment {

    private Long id;

    private Blob FileData;

    private String FileName;

    

    public Attachment(Long id,Blob FileData, String FileName) {

        this.id = id;

        this.FileData = FileData;

        this.FileName = FileName;

    }

    public Long getId() {

        return id;

    }

    public void setId(Long id) {

        this.id = id;

    }

    public Blob getFileData() {

        return FileData;

    }

    public void setFileData(Blob FileData) {

        this.FileData = FileData;

    }

    public String getFileName() {

        return FileName;

    }

    public void setFileName(String FileName) {

        this.FileName = FileName;

    }

}

 

 

 

import java.io.IOException;

import java.io.InputStream;

import java.sql.Blob;

import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

 

 

import javax.naming.Context;

import javax.naming.InitialContext;

import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.sql.DataSource;

 

 

@WebServlet("/downloadAttachment")

public class DownloadAttachmentServlet extends HttpServlet {

   private static final long serialVersionUID = 1L;

   @Override

   protected void doGet(HttpServletRequest request, HttpServletResponse response)  //다운로드는 빨라야 돼

           throws ServletException, IOException {

       Connection conn = null;

       try {

           // Get Database Connection.

           // (See more in JDBC Tutorial).

 

 

           Context ctx = new InitialContext();

           

            DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/sec");

           

            conn = ds.getConnection();

            conn.setAutoCommit(false);

 

 

           Long id = null;

           try {

               id = Long.parseLong(request.getParameter("id"));

           } catch (Exception e) {

           }

           Attachment atc = getAttachmentFromDB(conn, id);

           if (atc == null) {

               // No record found.

               response.getWriter().write("No data found");

               return;

           }

           // file1.zip, file2.zip

           String fileName = atc.getFileName();

           System.out.println("File Name: " + fileName);

           // abc.txt => text/plain

           // abc.zip => application/zip

           // abc.pdf => application/pdf

           String contentType = this.getServletContext().getMimeType(fileName);

           System.out.println("Content Type: " + contentType);

           response.setHeader("Content-Type", contentType);

           response.setHeader("Content-Length", String.valueOf(atc.getFileData().length()));

           response.setHeader("Content-Disposition", "inline; filename=\"" + atc.getFileName() + "\"");

           // For big BLOB data.

           Blob fileData = atc.getFileData();

           InputStream is = fileData.getBinaryStream();

           byte[] bytes = new byte[1024];

           int bytesRead;

           while ((bytesRead = is.read(bytes)) != -1) {

               // Write image data to Response.

               response.getOutputStream().write(bytes, 0, bytesRead);

           }

           is.close();

       } catch (Exception e) {

           throw new ServletException(e);

       } finally {

           this.closeQuietly(conn);

       }

   }

   private Attachment getAttachmentFromDB(Connection conn, Long id) throws SQLException {  

       String sql = "Select a.Id,a.File_Name,a.File_Data,a.Description "//

               + " from Attachment a where a.id = ?";

       PreparedStatement pstm = conn.prepareStatement(sql);

       pstm.setLong(1, id);

       ResultSet rs = pstm.executeQuery();

       if (rs.next()) {

           String fileName = rs.getString("File_Name");

           Blob fileData = rs.getBlob("File_Data");

           String description = rs.getString("Description");

           return new Attachment(id, fileData, description);

       }

       return null;

   }

   private void closeQuietly(Connection conn) {

       try {

           if (conn != null) {

               conn.close();

           }

       } catch (Exception e) {

       }

   }

}

 

 

 

import java.io.IOException;

import java.io.InputStream;

import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

 

 

import javax.naming.Context;

import java.sql.*;

import javax.sql.*;

import javax.naming.InitialContext;

import javax.servlet.RequestDispatcher;

import javax.servlet.ServletException;

import javax.servlet.annotation.MultipartConfig;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.servlet.http.Part;

import javax.sql.DataSource;

 

파일 업로드 DB 연동 클래스

@WebServlet("/uploadToDB")

@MultipartConfig(fileSizeThreshold = 1024 * 1024 * 2, // 2MB

        maxFileSize = 1024 * 1024 * 10, // 10MB

        maxRequestSize = 1024 * 1024 * 50) // 50MB

public class UploadToDBServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    @Override

    protected void doGet(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

        RequestDispatcher dispatcher = request.getServletContext().getRequestDispatcher("/WebContent/uploadToDB.jsp");

        dispatcher.forward(request, response);

    }

    @Override

    protected void doPost(HttpServletRequest request, HttpServletResponse response) //올리는건 ㄷ ㅓ신중히

            throws ServletException, IOException {

        Connection conn = null;

        try {

            // Connection to Database

            // (See more in JDBC Tutorial).

   

            Context ctx = new InitialContext();

            

            DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/sec");

            

            conn = ds.getConnection();

            conn.setAutoCommit(false);

            String description = request.getParameter("description");

            // Part list (multi files).

            for (Part part : request.getParts()) {

                String fileName = extractFileName(part);

                if (fileName != null && fileName.length() > 0) {

                    // File data

                    InputStream is = part.getInputStream();

                    // Write to file

                    this.writeToDB(conn, fileName, is, description);

                }

            }

            conn.commit();

            // Upload successfully!.

         

            response.sendRedirect(request.getContextPath() + "/uploadToDBResults");

           

            

        } catch (Exception e) {

            e.printStackTrace();

            request.setAttribute("errorMessage", "Error: " + e.getMessage());

            RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/WebContent/uploadToDB.jsp");

            dispatcher.forward(request, response);

        } finally {

            this.closeQuietly(conn);

        }

    }

    private String extractFileName(Part part) {

        // form-data; name="file"; filename="C:\file1.zip"

        // form-data; name="file"; filename="C:\Note\file2.zip"

        String contentDisp = part.getHeader("content-disposition");

        String[] items = contentDisp.split(";");

        for (String s : items) {

            if (s.trim().startsWith("filename")) {

                // C:\file1.zip

                // C:\Note\file2.zip

                String clientFileName = s.substring(s.indexOf("=") + 2, s.length() - 1);

                clientFileName = clientFileName.replace("\\", "/");

                int i = clientFileName.lastIndexOf('/');

                // file1.zip

                // file2.zip

                return clientFileName.substring(i + 1);

            }

        }

        return null;

    }

    private Long getMaxAttachmentId(Connection conn) throws SQLException {

        String sql = "Select max(a.id) from Attachment a";

        PreparedStatement pstm = conn.prepareStatement(sql);

        ResultSet rs = pstm.executeQuery();

        if (rs.next()) {

            long max = rs.getLong(1);

            return max;

        }

        return 0L;

    }

    private void writeToDB(Connection conn, String fileName, InputStream is, String description) throws SQLException {

        String sql = "Insert into Attachment(Id,File_Name,File_Data,Description) " //

                + " values (?,?,?,?) ";

        PreparedStatement pstm = conn.prepareStatement(sql);

        Long id = this.getMaxAttachmentId(conn) + 1;

        pstm.setLong(1, id);

        pstm.setString(2, fileName);

        pstm.setBlob(3, is);

        pstm.setString(4, description);

        pstm.executeUpdate();

    }

    private void closeQuietly(Connection conn) {

        try {

            if (conn != null) {

                conn.close();

            }

        } catch (Exception e) {

        }

    }

}

 

 

 

 

 

 

 

 

'Project' 카테고리의 다른 글

[툰츄]  (0) 2019.11.06
[부귀영화-영화 추천 서비스]  (0) 2019.10.25
[Hearable App-청각장애인용 스마트 앱]  (3) 2019.10.25
[MARK- 길건너기 2D 게임]  (0) 2019.10.25
[hearable watch-청각장애인용 스마트 워치]  (0) 2019.10.25

1)한줄요약 : 머신러닝을 활용한 위험소리알림,오픈소스 활용한 음성인식기능,SOS기능,보호자 등록 기능을 가진 안드로이드 앱을 제작

+비상알림벨: 경적,화재경보음,아기울음소리 등 위험소리를 감지하여 그 종류를 알려준다. 소리데이터 즉각적인 인지를 위해 진동을 발생시키고, 소리를 분석하여 화면에 이미지로 출력한다.          

+소음측정기: 주변의 소음정도를 측정해 적절한 발화를 돕는다. 데시벨을 측정해 크기에 맞춰 LED를 점등시킨다.

+원터치 신고: 사회적 약자인 장애인을 겨냥한 범죄를 즉각 대처할 수 있도록 돕는다. 버튼을 특정 패턴으로 누르면 작동되어, 실시간으로 사용자의 위치와 녹음 파일을 서버로 전송한다.

+음성인식: 원활한 대화를 위해 상대방의 음성을 인식하여 모니터에 텍스트로 출력한다.

 

2)본인 역할 : 위험소리알림기능을 전담함. mfcc로 wav파일 특징값을 추출하고 ,svm으로 모델에 학습시켜 샘플의 분류결과값을 지정. 자신의 역할을 끝낸 뒤  안드로에드에서 모듈들을 합치는 것을 도와줌.

+팀원:천재영(웹),박진청(데이터베이스),이은경(소음측정기,음성인식),박신혜(원터치신고,구글맵)

 

3)본인이 사용한 스킬 : JAVA,Machine Learning(MFCC+SVM)

+팀원스킬: Google Map Api, Naver Speech Api,Android,PHP,Mysql

 

4)힘들었던 점: 

+머신러닝이 어렵고 낯설었던 점->기술 레퍼런스,구조도를 활용해 맥락을 파악하려고 노력하며 디버깅

+머신러닝 분류기 선택할 때 팀원들을 설득하던 것->분류기마다 특성을 정리해 SVM이 더 적합한 이유를 얘기

+추출기의 출력 포맷이 분류기의 입력 포맷과 달랐는데 추출기 내부 함수를 수정하기 어려웠음->다른 IDE에서 미니 전처리 프로그램을 따로 만듬. 추후에 내부 함수 또한 수정하는데 성공했음.

 

[전체구조도]

 

 

 

[미니전처리기를 통해 포맷팅을 한 결과]

 

[제공되는 GUI를 활용하는 모습- 라이브러리는 livsvm 사용]

[실제 프로젝트 결과 모델의 분류 정도]

 

 

[실제 완성본 모습-데시벨 증가하는 모습, 분류해서 push 알림으로 도착한 모습, 보호자 로그인 기능..(다른 기능들은 사진이 없다)]

 

 

 

 

 


그 외의 자료들...

 

[주요 코드 1]

 

package edu.iitb.frontend.audio.feature;

import java.io.DataOutputStream;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.util.Vector;

import javax.sound.sampled.AudioInputStream;

import javax.sound.sampled.AudioSystem;

import javax.sound.sampled.UnsupportedAudioFileException;

import edu.iitb.frontend.audio.util.AudioPreProcessor;

import edu.iitb.frontend.audio.util.MFCC;

import java.io.BufferedWriter;

import java.io.FileWriter;

import java.io.IOException;

 

 

public class FeatureFileExtractor {

    static float sampleRate = 8000;

    public static int newWindowSize = 205;

    public static int hopsize = 80;

    static int numberCoefficients = 13;

    static double minFreq = 133;

    static double maxFreq = 3500;

    static int numberFilters = 31;

    /*    테스트 코드

    public static void main(String argv[]) throws IOException, IllegalArgumentException, UnsupportedAudioFileException {

        FeatureFileExtractor t = new FeatureFileExtractor();

        t.computeFeatures("siren15", "/Users/KCE/Desktop/capstone/total_train_wav/siren", "/Users/KCE/Desktop/capstone/total_train_wav/siren");

    }*/

    static int label = 1;  //분류값

 

    public static void computeFeatures(String fileName, String inputFolder, String outputFolder)   //문제의 포맷팅 처리 부분..기존에 visual stuio로 수정했지만 eclipse에서도 수정할 수 있게 됐다!

            throws IllegalArgumentException, IOException, UnsupportedAudioFileException {

 

        // WAV파일 읽음

        String wavFile = inputFolder + "/" + fileName + ".wav";

        System.out.println("converting " + wavFile + " to mfc");

        File soundfile = new File(wavFile);

        AudioInputStream audioIn = AudioSystem.getAudioInputStream(soundfile);

        AudioPreProcessor in = new AudioPreProcessor(audioIn, sampleRate);

        boolean useFirstCoefficient = true;

        

        //MFCC처리 

        MFCC feat = new MFCC(sampleRate, windowSize, numberCoefficients, useFirstCoefficient, minFreq, maxFreq,

                numberFilters);

        Vector<double[]> features = feat.process(in, audioIn);

        System.out.println("Vector Size :" + features.size());

 

        // 포맷팅

        BufferedWriter out = new BufferedWriter(new FileWriter("/Users/KCE/Desktop/capstone/not_trained_data/test.txt"));

        try {

            // create file output stream

            double arr[];

            for (int i = 0; i < features.size(); i++) {

                arr = features.get(i);

                if ((float) arr[0] < 30 && (float) arr[0] > -30) { // null

                    System.out.print(label + " "); // label

                    out.write(label + " ");        // label

                }

                for (int j = 0; j < arr.length; j++) {

                    if ((float) arr[j] < 30 && (float) arr[j] > -30) { // null

                        System.out.print(j + 1 + ":" + (float) arr[j] + " ");

                        out.write(j + 1 + ":" + (float) arr[j] + " ");

                        if (j == arr.length - 1)

                            System.out.println();

                        //String numberAsString = new Float((float) arr[j]).toString(); // float -> string

                        //out.write(numberAsString + " ");

                    }

                }

                if ((float) arr[0] < 30 && (float) arr[0] > -30) // null

                    out.write("\n");

            }

            out.flush();

            out.close();

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

}

 

 

 

 

[주요 코드 2]

 

import java.io.IOException;

import javax.sound.sampled.UnsupportedAudioFileException;

import edu.iitb.frontend.audio.feature.FeatureFileExtractor;

 

public class test {

 

    public static void main(String argv[]) throws IOException, IllegalArgumentException, UnsupportedAudioFileException

    {

        FeatureFileExtractor Feature = new FeatureFileExtractor();   

        Feature.computeFeatures("",                 // wavfile_name

                                "/Users/KCE/Desktop/capstone/total_train_wav/bark",     // input_file_dir

                                "/Users/KCE/Desktop/capstone/bark");    // output_file_dir

        svm_predict Predict = new svm_predict();

        String dir[] = {"/Users/KCE/Desktop/capstone/not_trained_data/test.txt",             // test_file(예측 시도해 볼 입력 파일)

                        "/Users/KCE/Desktop/capstone/model/traintrain.txt.model",    // model_file(모델파일이 있는 경로)

                        "/Users/KCE/Desktop/capstone/model/traintrain.txt.out"};        // output_file(예측 결과가 저장되는 경로)

        Predict.main(dir);   //만들어진 모델로 예측

        System.out.println(Predict.case_num);

        if(Predict.case_num==1)  //무슨 소리인지 분류 결과값 리턴

            System.out.println("baby");

        else if(Predict.case_num==2)

            System.out.println("bark");

        else if(Predict.case_num==3)

            System.out.println("drill");

        else if(Predict.case_num==4)

            System.out.println("fire");

        else if(Predict.case_num==5)

            System.out.println("siren");

    }

    

}

 

 

[프로젝트 진행사항 전달]

 

+참고자료: http://keunwoochoi.blogspot.kr/2016/01/blog-post.html : 다른 분류기를 사용하여 음악장르 분류 포스팅한 블로그

 

설명: 왼쪽부터 머신러닝 프로세스, 사용된 mfcc 파일,wav 파일이다.

원데이터는 분석을 위해 mp3아닌 wav파일 사용,프레임 길이 고려하여 5초 단위로 잘랐음. 축적된 데이터는 아기울음소리, 개짖는 소리, 사이렌소리,소방벨 소리 총 81개의 파일. 

 

 

 

 

 

'Project' 카테고리의 다른 글

[툰츄]  (0) 2019.11.06
[부귀영화-영화 추천 서비스]  (0) 2019.10.25
[WaterMelon-음원 사이트]  (0) 2019.10.25
[MARK- 길건너기 2D 게임]  (0) 2019.10.25
[hearable watch-청각장애인용 스마트 워치]  (0) 2019.10.25

1)한줄요약 : 유니티와 BFS알고리즘을 활용하여 기존의 지뢰찾기와 길찾기를 접목시킨 2D 게임을 제작

+룰:출발지에서 목적지까지 구멍들을 피해서 가장 적은 이동으로 도착해야한다.

가로,세로축의 트랩 수를 알려주는 등대와 자신  근처의 트랩 수를 알려주는 카운터는 추론의 보조장치가 된다.

게임중 목숨의 수는 줄어들 수 있고 아이템을 활용할 수 있다.

2)본인 역할 : 알고리즘 구현(BFS), 스토리 구성 

+팀원:ㅎㅈㅎ(PL,알고리즘 구현),ㄳㅎ(UI,스토리)

 

3)본인이 사용한 스킬 : C#,Unity

+팀원스킬: Google Map Api, Naver Speech Api,Android,PHP,Mysql

 

4)힘들었던 점: 

+팀원이 구조체에 대한 개념, 반복문으로 PS 하는 방법을 모르는 상태였어서 if~else가 백줄 가까이 작성되있었다. 

분담 후에 서로 진도 확인이나 결과물을 2주 가까이 한번도 점검하지 않았기 때문에 전혀 모르고 있었다. 

이미 열심히 만든 코드를 수정하는게 너무 미안했지만 이런 과정을 통해 알아가는거라고 생각을 다시 잡았다.

객체를 사용하고 이중포문을 이용해(Light House 코드..) 코드를 20줄 가까이로 최적화 시켰다. 

나의 첫 프로젝트였고 이 경험에서 나는 소통의 중요성을 배웠다.

 

5) 코드가 있는 깃허브 주소 (https://github.com/hun2ya9/2017-MARK)

 

 

[UI]

 

 

[오브젝트 소개]

[플레이어의 라이프는 게임실행 내내 반복되는 update함수에서 체크합니다. 마우스 입력을 통해 8방위로 이동가능하고

아이템을 활용하여 게임을 진행합니다.]

 

[ 플레이어 이동은 레이캐스트로 구현,마우스 클릭시 카메라로 부터 가상의 빔을 쏴서 해당 위치가 타일이면 플레이어가 그 위치로 이동방식이다.

이동 후 기존의 타일은 제거하고 새 플에이어 위치에 다시 생성함. 아이템획득은 box collider을 통해 구현함]

 

[길을 막는 경우같은 예외처리가 중요했다. 하지만 아래와 같은 이유들로, 기본적인 예외처리만 하고 길이 없는 경우에 재배치 하는걸로만 만들기로 함]

[동작 순서도]

[게임 시스템 구조-오브젝트 매니저가 게임의 핵심정보를 가지고 있으면 나머지 스크립트에서 그 정보를 활용함.

그리고 오브젝트 매니저는 UI매니저와 연결이 되어있고 UI에선 업적을 확인할때 파일매니저를 통해 참조를 함.]

 

[알고리즘 선택 이유]

최단경로를 찾을 때엔 많은 종류의 기법이 있었지만,

A*나 다익스트라,벨만포드 등은 그래프에 적합하고 우리의 게임은

맵 크기도 작을뿐더러 무엇보다 가중치가 없었기때문에 가장 간단한 BFS로 구현

 

 

[일정]

 

 


그 외의 자료..

[문제의 코드]

 

public void viewlight() //같은 행과 열에 지뢰가 몇 개 있는지

 

{

 

g = GameObject.FindGameObjectWithTag("Canvas").GetComponent<Text>();

 

int mapsize = Mathf.RoundToInt(script.gridWorldSize.x);

 

for (int x = 0; x < mapsize; x++) //등대 설치할 때 일차원배열에 바로 넣어줬으면 좋았으련만 시간이 없으므로 패스

 

for (int y = 0; y < mapsize; y++)

 

if (script.grid[x, y].is_lighthouse == true)

 

{

 

int trap_cnt = 0;

 

for (int i = 0; i < mapsize; i++)

 

{

 

if (script.grid[x, i].is_trap == true)

 

trap_cnt++;

 

if (script.grid[i, y].is_trap == true)

 

trap_cnt++;

 

}

 

g.text = trap_cnt + "";

 

GameObject G = Instantiate(Text);

 

G.transform.position = script.grid[x, y].worldPosition;

 

}

 

 

 

 

 

}

 

 

[유니티 환경. 그래픽 객체에 직접 코드를 연결한다는게 매우 편하고 놀라웠다.]

 

 

 

 

'Project' 카테고리의 다른 글

[툰츄]  (0) 2019.11.06
[부귀영화-영화 추천 서비스]  (0) 2019.10.25
[WaterMelon-음원 사이트]  (0) 2019.10.25
[Hearable App-청각장애인용 스마트 앱]  (3) 2019.10.25
[hearable watch-청각장애인용 스마트 워치]  (0) 2019.10.25

1)한줄요약 : 머신러닝으로 소리가 발생했을 때 위험한 소리인지 분석하여 릴리패드로 진동과 LED로 종류를 알림.

 

2)본인 역할 : 임베디드 파트. 릴리패드와 센서들을 연결하고 소리신호를 wav파일로 바꿔서 서버로 전송

+세부내용: 릴리패드의 마이크 센서에서 일정 수준 이상의 소음 입력되면 먼저 LED로 크기를 나타내고,

유의미한 소리라고 판단하여 녹음이 시작되며 서버에서 인공지능으로 분석후 종류를 알려줌.

+양우희(머신러닝),강창훈(임베디드,자바),김혜빈(머신러닝)

 

3)본인이 사용한 스킬 : Arduino, C ,LIly pad

+팀원스킬: Machind Learning(MFCC,HMM)+Matlab, JAVA

 

4)힘들었던 점: 

1.회로가 작동하도록 설계 했는데 전체를 연결하면 진동 센서가 동작 안함. 

->먼저 절차적으로 꼬이는 것이 있는지 확인을 해보고, 두번쨰로 모듈별로 코드를 분리해서 돌려봄.

-> 각각 돌렸을 때  이상이 없자 소프트웨어가 아닌 하드웨어 관점으로 접근해 생각해보았고 전력초과라는 원인을 찾아서 트랜지스터(전력을 증폭시키는 반도체소자)를 추가해서 해결.(아두이노로 연습당시)

2.분석에 필요한 녹음길이가 아두이노 메모리를 초과-> 실시간 전송 대신 서버에 저장해둔 녹음 파일을 분석하여 결과값을 자바의 시리얼 통신을 통해, LED를 이진수로 출력을 하였음.

 

5)아쉬운 점: 완성도가 높지 않았다. 추후에 버전 업그레이드 함( 링크:  포트폴리오로 정리한 "청각장애인용 스마트앱")

+왜 그랬을까? 하드웨어 스펙에 대한 조사가 충분히 이루어지지 않았다. (메모리 용량때문에 전체 wav 파일 녹음 불가, 시리얼통신으로 대체)

 

 

 

 

'Project' 카테고리의 다른 글

[툰츄]  (0) 2019.11.06
[부귀영화-영화 추천 서비스]  (0) 2019.10.25
[WaterMelon-음원 사이트]  (0) 2019.10.25
[Hearable App-청각장애인용 스마트 앱]  (3) 2019.10.25
[MARK- 길건너기 2D 게임]  (0) 2019.10.25

+ Recent posts