[原创]铲花检测项目技术文件

admin 发布于 2020-02-02 71 次阅读


本技术文件为原创,谢绝转载。
起源:我從2019年8月份開始接手這個項目,到12月底完工,縂歷時大概4個月,當然,并不是所有時間都在完成這個項目,畢竟還有考試和作業,最初我聽要求描述時,更像是爲了實現一個功能而啓用的臨時系統,加之時間有限,很多部分并沒有使用專業的,模塊化的開發方法,雖然完成系統的功能,但是很多細節需要花時間整理。本文截取项目中一些关键的技术进行解析,但是由于是企业项目(虽然目前没收到钱),故一些更深层的细节不会披露。

要求:這個系統叫做“鏟花檢測系統”,在一些大型的工具機械中,會有兩個金屬面進行滑動的情況,如果兩個平面完全貼合,則由於摩擦力的原因無法滑動,所以我們需要凹點使得機械進行滑動,但是同時需要一定的支撐面,此時工人師傅需要用工具把凹點鏟出來,而這個軟體就是檢測工人鏟的是否符合一定的百分比。
組件和功能:在這個系統中,分爲兩個組件(前端和後臺),前端主要由jsp寫成,通過html控制網頁内容,css控制佈局,js進行寫入控制或文件傳遞,java代碼進行資料和表格的動態輸出。

主界面:
1.拍照(選項卡):切換拍照功能,當點擊這個區域時,下方會顯示 “點擊這裏拍照” ,接受用戶拍照上傳。
2.選擇檔案(選項卡):切換檔案選擇功能,當點擊這個區域時,下方會顯示“點擊這裏上傳”,接受用戶從檔案選擇上傳。
3.點擊這裏拍照/點擊這裏上傳(按鈕):啓動相機或檔案選擇器,從設備中新添媒體。
4.高級管理(超鏈接):進入高級管理界面。

铲花资料输入页:
1.信息輸入組(輸入控件組):由多個輸入框組成,可以接受數字和英文的輸入,記錄用戶自定義的數值(機器工令,模組工單等)。
2.備注(輸入框):記錄備注,同樣是輸入框,不同的是,在這個框的數值支持中文。
3.提交檢測(按鈕):將用戶輸入的資料傳入記憶體(等待傳入資料庫)。
4.圖片位置框選區(控件浮層):允許用戶單擊圖片的任何位置,位置的坐標會傳入信息輸入組的檢測X位和檢測Y位中。

结果显示页:
1.信息顯示區域:將結果顯示給用戶。
2.返回首頁(超鏈接):提供返回首頁的地址。

检测管理页:
1.檢測管理(超鏈接)進入檢測管理頁面的入口。
2.報表下載(超鏈接):進入報表下載頁面的入口。
3.操作記錄(超鏈接):進入操作記錄頁面的入口。
4.系統設置(超鏈接):進入系統設置頁面的入口。

单个铲花信息管理:
1.查看(超鏈接):對整個檢測的影像進行查看。
2.查看(超鏈接):對於用戶自定義的檢測區域進行查看(100*100)。
3.刪除(超鏈接):對這筆資料進行刪除。
4.編輯(超鏈接):對資料進行編輯。

之后还有若干页面和功能省略。

Servlet结构如下:

网页结构如下:
在前端文件結構中,主要有以下幾個重要模組:
1.index.jsp—這是用戶的主要頁面,用戶可以在這個頁面進行拍照和上傳文件,它通過js實現對頁面組件控制,希望對用戶行爲進行適當的引導。我們使用表單對資料傳遞到後臺的servlet。
2.userInput.jsp—主要對index頁面的影像資料進行接收,它允許用戶輸入一些資料,注意在這一步我們只是將資料保存到記憶體中,等到反饋結果到來的時候再一起保存到資料庫。
3.result.jsp—主要顯示檢測的結果,並將結果保存在資料庫。
4.setting.jsp—是設置的主頁面,用來進入不同設置模塊的入口。
5.sinfo.jsp—主要從資料庫中檢索出需要的資料並提供查看圖片,編輯或刪除等操作的入口。
6.system.jsp—用來設置系統的上下限數值等運轉資料。
7.iplist.jsp—用來顯示訪客信息。
8.pdfdownload.jsp—用來下載pdf。
9.editscriping.Jsp—用來對單個鏟花檢測信息進行修改。
同时也包括後端模組對資料進行邏輯處理
1.uploadImg.java—主要對圖片進行上傳到伺服器的處理
2.result.java—進行資料的暫存和處理,呼叫檢測程式,接受並發送檢測結果到前臺。
3.database.java—對資料庫進行控制,每個資料庫操作都是一個獨立的函式。
4.delScrapingInfoSer.java—對鏟花資料進行刪除
5.downloadpdf.java—對鏟花資料進行下載
6.editScr.java—對鏟花資料進行編輯
7.parameter.java—對全局參數進行保存
組件解讀:説完了文件結構,我們開始對每個文件進行逐個解析,在解析的過程中,我們會交織前端和後臺,盡量還原一個完整的執行過程。但是對於css等佈局内容,並不在我們描述的範圍之内。
<div id="b2" style="display:none;">
     <form action="uploadImg?method=upload&way=fromAlbum" method="post"
		enctype="multipart/form-data">
		
		<div class="dicBoxOut">
		<input type="file" name="headShot1" class="headShot" onchange="show(this)">
		 <div id="dicBoxIn2">點擊這裏上傳</div>
		</div>
		
		<div id="comfirmArea2" style="display:none;"><br/><br/>
		<input type="submit" id="submitclass1" class="bigredsize2" value="從相冊上傳" onclick="button2gray()"><br/>
		</div>
		
	</form>
	<br/>
	</div>

上述代碼是index.jsp中的核心代碼,我們可以看到54行有個div隱藏的代碼,我們配合js可以先將這個區域隱藏,等到用戶點擊的時候才展現這個區域,這樣我們的界面會比較有條理,不至於用戶看到一堆代碼不知道點擊哪個,同理在63行的時候,我們同樣能看到一個隱藏代碼,以保證用戶在點擊上傳圖片才能看到確認上傳按鈕,防止多次上傳。

function showAlbum(imgObj)
        {document.getElementById("b1").style.display = "block";
         document.getElementById("b2").style.display = "none";
         document.getElementById("b3").style.display = "none";
         document.getElementById("b4").style.display = "none";}

至於div顯示和隱藏的代碼如上圖所示,并不是非常複雜。

<div id="down">
		<script>		
			function show(file){	
				var reader = new FileReader();
				var img = document.getElementById('img');
					reader.onload = function(evt){
					img.width  =  "960";
			        img.height =  "540";
					img.src = evt.target.result;
				}
			    reader.readAsDataURL(file.files[0]);
			    document.getElementById("comfirmArea").style.display = "block";
			    document.getElementById("comfirmArea2").style.display = "block";
			}	
		</script>
<img id="img" src=""/>
</div>

我們使用js進行圖片的預覽,儅用戶上傳一張相片,我們會將它的縮略圖顯示在這個網頁的下面。

uploadImg.java
String time=new Date().getTime()+"";
	    String way=request.getParameter("way");
		Part part = null;
		if("fromAlbum".equals(way)) {part = request.getPart("headShot1");}
		else if("fromLen".equals(way)) {part = request.getPart("headShot2");}
		else {}
		String newFileName = time+".jpg";
		String filePath = parameter.path;
	    File f = new File(filePath);
		if (!f.exists()) {f.mkdirs();}
		part.write(filePath + "/" + newFileName);
		System.out.println("=========>"+filePath + "/" + newFileName);
		response.sendRedirect("userInput.jsp?id="+time);

在57行中我們要獲取系統時間用以對影像進行編號,同時,我們對區域資源進行獲取,并將其保存到本地伺服器上。

<form action="result" method="post">
<div style="display:none;">
影像識別號: <input type="text" id="imageno" name="imageno" readonly="readonly" value=<% request.getParameter("id"); %>  disabled="disabled"><br/>
</div>
<div id="alltext">
檢測X位 : <input type="text" class="uin" id="xinput" name="xinput" value="-1"><br/>
檢測Y位 : <input type="text" class="uin" id="yinput" name="yinput" value="-1"><br/><br/>
機器型號: <input type="text" class="uin" id="ma" name="ma" value="-1"><br/>
操作工號: <input type="text" class="uin" id="mb" name="mb" value="-1"><br/>
機器工令: <input type="text" class="uin" id="mc" name="mc" value="-1"><br/>
模組工單: <input type="text" class="uin" id="md" name="md" value="-1"><br/><br/>
情況備注: <br/><textarea type="text" class="uix" id="me" name="me" value="-1" ></textarea><br/><br/>
</div>
<br/>
<input type="submit" class="uen" id="okbutton" name="okbutton" value="提交檢測" onclick="button2gray()">
<div id="note" style="display:none;">正在檢測,請稍後...</div>
</form>

我們直接用表單的形式把前端輸入的資訊傳入servlet,需要注意的是id和class是識別區域的重要組成部分。我們給輸入框一個默認的數值“-1”,在後期的程式處理中,用以代替空格,防止出現空指針的情況。另外有一個隱藏的區域“影像識別號”,它從上一個頁面接收而來,同時準備傳遞到下一個選項。

function rectClick(event) {
		var t1=document.getElementById("xinput");
 		t1.value=parseInt(event.offsetX);
		var t2=document.getElementById("yinput");
		t2.value=parseInt(event.offsetY);
        var oEvent=event;
		var docW=document.body.clientWidth;
		var leftoffset=parseInt((docW-960)/2);
        var oDiv=document.createElement('div');
        var box = document.getElementById("addbox");  
        if(box){box.parentNode.removeChild(box);}  
        oDiv.id="addbox";
        oDiv.style.left=event.offsetX+leftoffset+'px'; 
        oDiv.style.top=event.offsetY+700+'px'; 
        oDiv.style.border='10px solid #FF0000'; 
        oDiv.style.position='absolute'; 
        oDiv.style.width='0px';
        oDiv.style.height='0px'; 
        document.body.appendChild(oDiv); 
      }

由於我們要對檢測的圖片進行人工取樣,所以這就需要我們的滑鼠點擊一個位置,會出現相應點的坐標。我們嘗試將這一功能進行實踐。
接下來我們要著重説一下result文件,在這個文件中,我們完成了檢測和參數儲存與處理等重要的任務。

		 String x = request.getParameter("xinput");
	     String y = request.getParameter("yinput");
	     String ma = request.getParameter("ma");
	     String mb = request.getParameter("mb");
	     String mc = request.getParameter("mc");
	     String md = request.getParameter("md");

這幾句主要將用戶輸入的參數傳遞到記憶體,

int x2int = Integer.parseInt(x);
		    int y2int = Integer.parseInt(y);
	        int realx=0;int realy=0;
		    if(x2int!=-1&&y2int!=-1) {
	        int picW=sourceImg.getWidth();
	        int picH=sourceImg.getHeight();
	        if(x2int<=0) {x2int=1;}
		    if(y2int<=0) {y2int=1;}
		     double dx=picW*1.0/960*1.0;
		     double dy=picW*1.0/540*1.0;
	        realx=(int)(x2int*dx);
	        realy=(int)(y2int*dy);
	        }else {
	        	realx=-1;
	        	realy=-1;
	        }

這裏主要是對用戶上傳的圖像和點擊的圖像進行坐標尺寸轉換,有時候,用戶會上傳非常大的圖片,這時候如果直接顯示在網頁上,不但非常不美觀也很難做定位,所以我們在前端顯示的圖片都是固定大小,我們使用比例計算出實際的圖像大小。

if(ppi2int >= lppi && ppi2int <= mppi && ppi2int >= lpop && pop2int <= mpop) {res=1;parameter.res=1; }else {res=0;parameter.res=0;}
	     try {d.insertScrapingInformation(imageno2int,realx,realy,ma,mb,mc,md, ppi2int, pop2int, res,me);
			  response.sendRedirect("result.jsp");return;
	     } catch (Exception e) {e.printStackTrace();}

我們首先檢驗數值是否符合我們設定的要求,防止處理不合理的數據,在檢查無誤后寫入資料庫,這些寫入的數值都是從前端傳來的,我們把它寫入資料庫,我們可以看到這個函數是出現在database.java中的。

public static void insertScrapingInformation(double imageno, int xno, int yno, String ma, String mb, String mc,
			String md, int ppi, int pop, int res, String me) throws Exception {
		Connection conn = init();
		PreparedStatement psql;
		psql = conn.prepareStatement(
				"insert into scraping(`imageno`,`xno`,`yno`,`ma`,`mb`,`mc`,`md`,`ppi`,`pop`,`res`,`me`) "
						+ "values(?,?,?,?,?,?,?,?,?,?,?)");
		psql.setDouble(1, imageno);
		psql.setInt(2, xno);
		psql.setInt(3, yno);
		psql.setString(4, ma);
		psql.setString(5, mb);
		psql.setString(6, mc);
		psql.setString(7, md);
		psql.setInt(8, ppi);
		psql.setInt(9, pop);
		psql.setInt(10, res);
		psql.setString(11, me);
		psql.executeUpdate();
	}

在資料的操作中。我們先獲得Connection物件,然後直接拼接並發送sql語句對資料進行插入

File f= new File("D://files//return.txt");
	     if(f.exists()) {f.delete();}
	     for(int i=0;i<5000;i++) {
	    	 if(f.exists()) {
	    	     String returnValue=readFile();
	    	     String returnValueArray[]=returnValue.split("@");
	    	     ppi=returnValueArray[0];
	    	     pop=returnValueArray[1];
	    	     parameter.ppi=Integer.parseInt(returnValueArray[0]);
	    	     parameter.pop=Integer.parseInt(returnValueArray[1]);
	    	     parameter.imageId=imageno;
	    	     break;
	    	 }
	    	 try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}
	     }

我們會啓動檢測程式並檢查是否有文件(return.txt)存在,它是檢測程式返回的值的文件,如果存在,我們會用“@”進行參數分割。然後將第一個,第二個參數分別作爲ppi和pop進行賦值。使用Thread.sleep實現每隔0.1秒檢測一次。

<div id="title">鏟花檢測報告</div>
<% if(parameter.res==1){%>
<div id="res1">合格</div>
<%}else{%>
<div id="res2">不合格</div>
<%} %>
<div id="detail"><br/>ID:<%out.print(parameter.imageId); %>  <br/>PPI:<%out.print(parameter.ppi); %>  <br/>POP:<%out.print(parameter.pop); %>% <br/><br/></div>
<div class="back"><a href="index.jsp">[返回首頁]</a></div>
</div>

我們使用jsp進行前端結果的顯示(給用戶)並動態顯示出標簽。

<%
String imageId="";
String imageId2="";
database d=new database();
int start=Integer.parseInt(request.getParameter("start"));
String all[]=d.queryScrapingInfo(start);
int pos=0;
for ( int i=0; i < all.length-13; i++){
	if(all[i]==null&&all[i+1]==null&&all[i+2]==null&&all[i+3]==null){
		pos=i;break;
	}
}
for ( int i=0; i < pos; i++){
if(i%13==0){
%>
<tr>
<% } %>
<td>
<% out.print(all[i]); 
	if(i%13==1){imageId=all[i];imageId2=all[i];}
%>
</td>

<% if(i%13==12){ %>
<td><a href="files/<%=imageId%>.jpg">查看</a></td>
<td><a href="files/<%=imageId%>c.jpg">查看</a></td>
<td><a href="delScrapingInfoSer?id=<%=imageId2%>">刪除</a></td>
<td><a href="editscraping.jsp?id=<%=imageId2%>&ma=<%=all[i-8]%>&mb=<%=all[i-7]%>&mc=<%=all[i-6]%>&md=<%=all[i-5]%>">編輯</a></td>
</tr>
<% } } %>

</table>
<% 
int pressBefore=1;
int pressNext=1;
if(start>=21){pressBefore=start-20;} 
pressNext=start+20;
%>
此作者没有提供个人介绍
最后更新于 2020-02-02