㈠ 求256色轉灰度圖 圖像平移 圖像旋轉 二值化 圖像縮放的代碼 c或c#或c++或java都行
c++ 加上 opencv 可以實現
㈡ java手寫體英文數字識別系統 識別預處理如何實現 採用什麼語言比較好
轉載1 引言
手寫體數字識別是文字識別中的一個研究課題,是多年來的研究熱點,也是模式識別領域中最成功的應用之一。由於識別類型較少,在實際生活中有深遠的應用需求,一直得到廣泛的重視。近年來隨著計算機技術和數字圖像處理技術的飛速發展,數字識別在電子商務、機器自動輸入等場合已經獲得成功的實際應用。盡管人們對手寫數字的研究己從事了很長時間的研究,並己取得了很多成果,但到目前為止,機器的識別本領還無法與人的認知能力相比,這仍是一個有難度的開放問題,所以對手寫數字識別的進一步研究,尋求如何更高效更准確更節能地實現手寫數字的自動錄入和識別的解決方案對提高經濟效益、推動社會發展都有深遠的意義。
近年來, 人工神經網技術發展十分迅速, 它具有模擬人類部分形象思維的能力, 為模式識別開辟了新的途徑, 成了模擬人工智慧的一種重要方法,特別是它的信息並行分布式處理能力和自學習功能等顯著優點, 更是激起了人們對它的極大的興趣。BP(Back Propagation)網路是神經網路中一種,是1986年由Rumelhart和McCelland為首的科學家小組提出,是一種按誤差逆傳播演算法訓練的多層前饋網路,可以很好地解決非線性問題,在函數逼近、模式識別和數據壓縮等方面都有很廣泛的應用。我們在認真地研究了神經網路的基本原理和機制的基礎上, 結合手寫體數字識別這一具體課題, 提出了用BP神經網路方法來實現手寫體數字識別的方案。
2 手寫體數字識別概述
2.1 手寫數字識別簡述
模式識別是六十年代初迅速發展起來的一門學科。由於它研究的是如何用機器來實現人及某些動物對事物的學習、識別和判斷能力,因而受到了很多科技領域研究人員的注意,成為人工智慧研究的一個重要方面。
字元識別是模式識別的一個傳統研究領域。從50年代開始,許多的研究者就在這一研究領域開展了廣泛的探索,並為模式識別的發展產生了積極的影響。
手寫體數字識別是多年來的研究熱點也是字元識別中的一個特別問題。手寫體數字識別在特定的環境下,如郵政編碼自動識別系統,稅表和銀行支票自動處理系統等一般情況。當涉及到數字識別時,人們往往要求識別器有很高的識別可靠性,特別是有關金額的數字識別時,如支票中填寫的金額部分,更是如此。因此針對這類問題的處理系統設計的關鍵環節之一就是設計出高可靠性和高識別率的手寫體數字識別方法。這個領域取得了飛速的發展,部分是由於更好的學習演算法,部分是由於更優良的訓練集。美國國家科學學會(NIST)建立了
一個包含60000個經過標注的數字的資料庫,它已經成為對新的學習演算法進行比較的性能測試標准。然而可以說還沒有哪個手寫體數字識別器達到完美的識別效果。
在過去的數十年中,研究者們提出了許許多多的識別方法,按使用的特徵不同,這些方法可以分為兩類:基於結構特徵的方法和基於統計特徵的方法。統計特徵通常包括點密度的測量、矩、特徵區域等。結構特徵通常包括園、端點、交叉點、筆劃、輪廓等,一般來說,兩類特徵各有優勢。例如,使用統計特徵的分類器易於訓練,而且對於使用統計特徵的分類器,在給定的訓練集上能夠得到相對較高的識別率;而結構特徵的主要優點之一是能描述字元的結構,在識別過程中能有效地結合幾何和結構的知識,因此能夠得到可靠性較高的識別結果。本文針對手寫數字識別選用BP神經網路這種基於傳統統計學基礎上的分類方法,用於分割和識別,並取得了較好的識別效果。
2.2 手寫數字識別的一般過程
手寫體數字識別的過程如圖2-1所示,一般分為預處理、特徵提取、數字串的分割、分類器、等模塊。原始圖像是通過光電掃描儀,CCD器件或電子傳真機等獲得的二維圖像信號。預處理包括對原始圖像的去噪、傾斜校正或各種濾波處理。手寫體數字具有隨意性,其字元大小、字間距、字內距變化很大,分割難度較大。手寫數字串的分割是其中最重要的環節,是制約識別率的瓶頸所在。去噪是預處理中極重要的環節。系統面對的是從實際環境中切分出的字元圖像,可能有粘連的邊框、隨機的墨點、切分不正確引入的其他字元筆劃等使前景點增加的雜訊,還可能有斷線等使背景增加的雜訊,目前適應各種環境的通用去噪演算法還不成熟。預處理中的規格化也不僅僅是同比例的放縮,它不僅要保持拓撲不變,更要最大限度地突出所取特徵。在眾多應用環境中,特徵提取、分類器、多分類器集成是整個識別系統的核心。大體上來說特徵可以分為結構特徵和統計特徵兩類。由於分類器的選擇取決於所提取的特徵,因此相應的識別方法便有結構方法和統計方法。
總之,從手寫體數字識別原理可見,手寫體數字識別技術主要包括以下幾點:
1)圖像預處理,包括彩色圖像轉成灰度圖像、二值化,歸一化,濾除干擾雜訊等;
2)基於數字圖像的特徵選擇和提取;
3)數字串的分割;
4)模式分類識別。
其中,第二和第四部分是手寫數字識別的重點,直接關繫到識別的准確率和效率,也是本論文研究的重點所在。
結果圖2-1 識別流程
2.3 手寫數字識別的一般方法及比較
手寫數字識別在學科上屬於模式識別和人工智慧的范疇。在過去的四十年中,人們提出了很多辦法獲取手寫字元的關鍵特徵,提出了許多識別方法和識別技術。這些手段分兩大類:
全局分析和結構分析。
多年的研究實踐表明,對於完全沒有限制的手寫數字,幾乎可以肯定:沒有一種簡單的方案能達到很高的識別率和識別精度,因此,最近這方面的努力向著更為成熟、復雜、綜合的方向發展。研究工作者努力把新的知識運用到預處理,特徵提取,分類當中。近年來,人工智慧中專家系統方法、人工神經網路方法已應用於手寫數字識別。在手寫數字識別的研究中,神經網路技術和多種方法的綜合是值得重視的方向。
針對模式特徵的不同選擇及其判別決策方法的不同,可將模式識別方法大致分為5大類這5種識別方法均可實現手寫數字識別,但它們特點不同,必須根據條件進行選擇。
(1)統計模式法
這是以同類模式具有相同屬性為基礎的識別方法。用來描述事物屬性的參量叫做待征,它可以通過模式的多個樣本的測量值統計分析後按一定準則來提取。例如:在手寫數字識別系統中,我們可以把每個數字的圖形分為若干個小方塊(圖),然後統計每一小方塊中的黑像素構成一個多維特徵矢量,作為該數字的特徵。必須注意的是:在選擇特徵時,用於各類模式的特徵應該把同類模式的各個樣本聚集在一起,而使不同類模式的樣本盡量分開,以保證識別系統能具有足夠高的識別率。
(2)句法結構方法
在形式語言和自動機的基礎上產生了句法結構這一方法。其基本原理是:對每一個模式都用一個句法來表示,而對一個待識別的未知樣本,通過抽取該樣本的基元來構造該樣本的句子,然後分析此句子滿足什麼樣的句法,從而推斷出他該屬於哪個模式類。這種方法的優點是它能反映模式的結構特徵,而且對模式的結構特徵變換不敏感,因此比較適合聯機識別。但是由於抽取字元的基元比較困難,因而不是特別適合用於離線識別,同時這一方法的理論基礎還不可靠,抗干擾能力比較弱。
(3)邏輯特徵法
就是其特徵的選擇對一類模式識別問題來說是獨一無二的,即在一類問題中只有1個模式具有某1種(或某1組合的)邏輯特徵,此方法律立了關於知識表示及組織,目標搜索及匹配的完整體系;對需通過眾多規則的推理達到識別目標的問題,有很好的效果,但當樣品有缺損,背景不清晰,規則不明確甚至有歧義時,效果不好。
(4)模糊模式方法
就是在模式識別過程中引入了模糊集的概念,由於隸屬度函數作為樣品與模板相似程度的量度,故能反映整體的、主要的特性,模糊模式有相當不勻稱的抗干擾與畸變,從而允許樣品有相當程度的干擾與畸變,但准確合理的隸屬度函數往往難以建立。目前有學者在研究,並將其引入神經網路方法形成模糊神經網路識別系統。
(5)神經網路方法
就是使用人工神經網路方法實現模式識別。可處理某些環境信息十分復雜,背景知識不清楚,推理規則不明確的問題,允許樣品有較大的缺損、畸變。神經網路方法的缺點是其模型在不斷豐富完善中,目前能識別的模式類不夠多,神經網路方法允許樣品有較大的缺損和畸變,其運行速度快,自適應性能好,具有較高的解析度。
上述幾種識別方法各有特點。結構法比較直觀,能較好反映事物的結構特性:問題是基元的提取很不容易,各基元的關系也比較復雜,抗干擾性能也較差。統計法用計算機來抽取特徵,比較方便,抗干擾性能強;缺點是沒有充分利用模式的結構特性。神經網路方法由於處理的並行性,可以快速同時處理大容量的數據,工作時具有高速度和潛在超高速,並且,網路的最終輸出是由所有神經元共同作用的結果,一個神經元的錯誤對整體的影響很小,所以其容錯性也非常的好。基於以上的考慮,本文的手寫數字識別採用了神經網路的方法。
3 圖像預處理與特徵提取
手寫體圖像數據在沒有進行一定的圖像預處理和特徵提取之前,不能立即應用到程序中進行神經網路訓練和字元識別工作。從圖像處理角度來說,手寫體的字元識別對字元是不是有顏色是不關心的,而對此圖像的清晰度是很關心的。所以在圖像進行一系列的圖像處理工作是很有必要的。圖像的預處理是正確、有效提取圖像特徵的基礎,有效的圖像特徵作為網路的輸入值才能進行正確的神經網路訓練和最終得到正確、有效的網路權重。
3.1 數字圖像預處理
3.1.1 灰度化處理
彩色圖像包含了大量的顏色信息,不但在存儲上開銷很大,在處理上也會降低系統的執行速度,因此在對圖像進行識別等處理中經常將彩色圖像轉變為灰度圖像,以加快處理速度。由彩色轉換為灰度的過程稱為灰度化處理。灰度圖像就是只有強度信息而沒有顏色信息的圖像,存儲灰度圖像只需要一個數據矩陣,矩陣每個元素表示對應位置像素的灰度值。彩色圖像的像素色為RGB(R,G,B),灰度圖像的像素色為RGB(r,r,r) ,R,G,B可由彩色圖像的顏色分解獲得。而R,G,B的取值范圍是0-255,所以灰度的級別只有256級。灰度化的處理方法主要有如下三種:最大值法、平均值法和加權平均值法。本文用到的加權平均值法來處理,即更換每個像素的顏色索引(即按照灰度映射表換成灰度值)。 權重選擇參數為:
紅:0.299
綠:0.587
藍:0.114
例如某像素點顏色對應的灰度值計算公式為:
NewPixColor?(BYTE)(0299*Red?0.587*Green?0.114*Blue) 系統輸入的源圖像支持3通道或者4通道圖像,支持Format24bppRgb, format32bppRgb, Format32bppArgb和Format8bppIndex這4種像素格式。
3.1.2 二值化處理
二值圖像是指整幅圖像畫面內僅黑、白二值的圖像。在數字圖像處理中,二值圖像佔有非常重要的地位。在實際的識別系統中,進行圖像二值變換的關鍵是要確定合適的閾值,使得字元與背景能夠分割開來,二值變換的結果圖像必須要具備良好的保形性,不丟掉有用的形狀信息,不會產生額外的空缺等等。採用二值圖像進行處理,能大大地提高處理效率。 二值化的關鍵在於閾值的選取,閾值的選取方法主要有三類:全局閾值法、局部閾值法、動態閾值法。全局閥值二值化方法是根據圖像的直方圖或灰度的空間分布確定一個閥值,並根據該閥值實現灰度圖像到二值化圖像的轉化。全局閥值方法的優點在於演算法簡單,對於目標和背景明顯分離、直方圖分布呈雙峰的圖像效果良好,但對輸入圖像量化雜訊或不均勻光照等情況抵抗能力差,應用受到極大限制。局部閥值法則是由像素灰度值和像素周圍點局部
灰度特性來確定像素的閥值的。Bernsen演算法是典型的局部閥值方法,非均勻光照條件等情況雖然影響整體圖像的灰度分布卻不影響局部的圖像性質,局部閥值法也存在缺點和問題,如實現速度慢、不能保證字元筆劃連通性、以及容易出現偽影現象等。動態閥值法的閥值選擇不僅取決於該像素灰度值以及它周圍像素的灰度值,而且還和該像素的坐標位置有關,由於充分考慮了每個像素鄰域的特徵,能更好的突出背景和目標的邊界,使相距很近的兩條線不會產生粘連現象。在圖像分割二值化中,自動閩值選取問題是圖像分割的關鍵所在。事實證明,閩值的選擇的恰當與否對分割的效果起著決定性的作用。
本文採用全局閾值的方法,實現將圖像二值化的功能。如果某個像素的值大於等於閾值,該像素置為白色;否則置為黑色。系統程序目前僅支持8bpp灰度圖像的轉換,閾值介於0~255之間,程序中取220。
3.1.3 去離散雜訊
原始圖像可能夾帶了雜訊,去雜訊是圖像處理中常用的手法。通常去噪用濾波的方法,比如中值濾波、均值濾波,本文中去除離散雜訊點採用中值濾波的方法。中值濾波法是一種非線性平滑技術,它將每一象素點的灰度值設置為該點某鄰域窗口內的所有象素點灰度值的中值,讓周圍的像素值接近的真實值,從而消除孤立的雜訊點。
3.1.4 字元分割
在識別時系統只能根據每個字元的特徵來進行判斷,為了最終能准確識別手寫體數字,必須將單個字元從處理後的圖像中逐個提取分離出來。具體做法是將圖像中待識別的字元逐個分離出來並返回存放各個字元的位置信息的鏈表。當把圖像分割完成後,從一定意義上來說便是形成了不同的小圖,每一張小圖就是一個數字,才能對這些小圖進行尺寸大小一致的調整。
3.1.5 細化
3.2 圖像特徵提取
特徵提取是字元識別中的一個重要組成部分,是模式識別的核心之一。經過預處理後,根據識別方法的要求抽取圖像特徵,作為識別的依據。一般而言,選擇的特徵一方面要求能夠足夠代表這個圖像模式,另一方面要求它們的數量盡可能少,這樣能有效地進行分類和較小的計算量。特徵提取的好壞會直接影響其識別的分類效果,進而影響識別率,因此特徵選擇是模式識別的關鍵。但是,目前還沒有一個有效的、一般的抽取、選擇特徵的方法。抽取、選擇特徵的方法都是面對問題的,因此針對不同的識別問題往往有不止一種的抽取、選擇特徵的方法。
㈢ 急!!,二值化後的圖像,用JAVA中值濾波演算法,去除椒鹽噪點!!!
椒鹽雜訊的話一般可以用中值濾波器去除, 中值濾波器很容易實現, 依此遍歷圖像中每個像素點, 每個像素點與其周圍的8個點像素值做一下排序操作, 找到這九個點中的中值點賦給當前遍歷點的像素就可以了, 演算法很簡單吧. 我這有c++的源碼, 樓主要想要的話發郵件到我的郵箱[email protected]我可以把程序發給你.
㈣ Sku超量閾值設置 java怎麼實現
較為常用的圖像二值化方法有:1)全局固定閾值;2)局部自適應閾值;3)OTSU等。局部自適應閾值則是根據像素的鄰域塊的像素值分布來確定該像素位置上的二值化閾值。這樣做的好處在於每個像素位置處的二值化閾值不是固定不變的,而是由其周圍鄰域像素的分布來決定的。亮度較高的圖像區域的二值化閾值通常會較高,而亮度較低的圖像區域的二值化閾值則會相適應地變小。不同亮度、對比度、紋理的局部圖像區域將會擁有相對應的局部二值化閾值。常用的局部自適應閾值有:1)局部鄰域塊的均值;2)局部鄰域塊的高斯加權和。
㈤ 用Java對圖像進行二值化處理時,kittler函數能直接用嗎
取點的RGB值,,,,和預設的值比較,大於是白、小於是黑
㈥ java代碼怎麼實現圖像二值化
較為常用的圖像二值化方法有:1)全局固定閾值;2)局部自適應閾值;3)OTSU等。
局部自適應閾值則是根據像素的鄰域塊的像素值分布來確定該像素位置上的二值化閾值。
這樣做的好處在於每個像素位置處的二值化閾值不是固定不變的,而是由其周圍鄰域像素的分布來決定的。
亮度較高的圖像區域的二值化閾值通常會較高,而亮度較低的圖像區域的二值化閾值則會相適應地變小。不同亮度、對比度、紋理的局部圖像區域將會擁有相對應的局部二值化閾值。
常用的局部自適應閾值有:
1)局部鄰域塊的均值;
2)局部鄰域塊的高斯加權和。
㈦ 如何用java去除圖片水印
//運行以下程序即可
publicclassImageInit{
BufferedImageimage;
privateintiw,ih;
privateint[]pixels;
publicImageInit(BufferedImageimage){
this.image=image;
iw=image.getWidth();
ih=image.getHeight();
pixels=newint[iw*ih];
}
publicBufferedImagechangeGrey(){
PixelGrabberpg=newPixelGrabber(image.getSource(),0,0,iw,ih,
pixels,0,iw);
try{
pg.grabPixels();
}catch(InterruptedExceptione){
e.printStackTrace();
}
//設定二值化的域值,默認值為100
intgrey=100;
//對圖像進行二值化處理,Alpha值保持不變
ColorModelcm=ColorModel.getRGBdefault();
for(inti=0;i<iw*ih;i++){
intred,green,blue;
intalpha=cm.getAlpha(pixels[i]);
if(cm.getRed(pixels[i])>grey){
red=255;
}else{
red=0;
}
if(cm.getGreen(pixels[i])>grey){
green=255;
}else{
green=0;
}
if(cm.getBlue(pixels[i])>grey){
blue=255;
}else{
blue=0;
}
pixels[i]=alpha<<24|red<<16|green<<8|blue;//通過移位重新構成某一點像素的RGB值
}
//將數組中的象素產生一個圖像
ImagetempImg=Toolkit.getDefaultToolkit().createImage(
newMemoryImageSource(iw,ih,pixels,0,iw));
image=newBufferedImage(tempImg.getWidth(null),
tempImg.getHeight(null),BufferedImage.TYPE_INT_BGR);
image.createGraphics().drawImage(tempImg,0,0,null);
returnimage;
}
publicBufferedImagegetMedian(){
PixelGrabberpg=newPixelGrabber(image.getSource(),0,0,iw,ih,
pixels,0,iw);
try{
pg.grabPixels();
}catch(InterruptedExceptione){
e.printStackTrace();
}
//對圖像進行中值濾波,Alpha值保持不變
ColorModelcm=ColorModel.getRGBdefault();
for(inti=1;i<ih-1;i++){
for(intj=1;j<iw-1;j++){
intred,green,blue;
intalpha=cm.getAlpha(pixels[i*iw+j]);
//intred2=cm.getRed(pixels[(i-1)*iw+j]);
intred4=cm.getRed(pixels[i*iw+j-1]);
intred5=cm.getRed(pixels[i*iw+j]);
intred6=cm.getRed(pixels[i*iw+j+1]);
//intred8=cm.getRed(pixels[(i+1)*iw+j]);
//水平方向進行中值濾波
if(red4>=red5){
if(red5>=red6){
red=red5;
}else{
if(red4>=red6){
red=red6;
}else{
red=red4;
}
}
}else{
if(red4>red6){
red=red4;
}else{
if(red5>red6){
red=red6;
}else{
red=red5;
}
}
}
intgreen4=cm.getGreen(pixels[i*iw+j-1]);
intgreen5=cm.getGreen(pixels[i*iw+j]);
intgreen6=cm.getGreen(pixels[i*iw+j+1]);
//水平方向進行中值濾波
if(green4>=green5){
if(green5>=green6){
green=green5;
}else{
if(green4>=green6){
green=green6;
}else{
green=green4;
}
}
}else{
if(green4>green6){
green=green4;
}else{
if(green5>green6){
green=green6;
}else{
green=green5;
}
}
}
//intblue2=cm.getBlue(pixels[(i-1)*iw+j]);
intblue4=cm.getBlue(pixels[i*iw+j-1]);
intblue5=cm.getBlue(pixels[i*iw+j]);
intblue6=cm.getBlue(pixels[i*iw+j+1]);
//intblue8=cm.getBlue(pixels[(i+1)*iw+j]);
//水平方向進行中值濾波
if(blue4>=blue5){
if(blue5>=blue6){
blue=blue5;
}else{
if(blue4>=blue6){
blue=blue6;
}else{
blue=blue4;
}
}
}else{
if(blue4>blue6){
blue=blue4;
}else{
if(blue5>blue6){
blue=blue6;
}else{
blue=blue5;
}
}
}
pixels[i*iw+j]=alpha<<24|red<<16|green<<8
|blue;
}
}
//將數組中的象素產生一個圖像
ImagetempImg=Toolkit.getDefaultToolkit().createImage(
newMemoryImageSource(iw,ih,pixels,0,iw));
image=newBufferedImage(tempImg.getWidth(null),
tempImg.getHeight(null),BufferedImage.TYPE_INT_BGR);
image.createGraphics().drawImage(tempImg,0,0,null);
returnimage;
}
publicBufferedImagegetGrey(){
ColorConvertOpccp=newColorConvertOp(
ColorSpace.getInstance(ColorSpace.CS_GRAY),null);
returnimage=ccp.filter(image,null);
}
//
(){
RescaleOprop=newRescaleOp(1.25f,0,null);
returnimage=rop.filter(image,null);
}
//Blurby"convolving"theimagewithamatrix
publicBufferedImagegetBlur(){
float[]data={.1111f,.1111f,.1111f,.1111f,.1111f,.1111f,
.1111f,.1111f,.1111f,};
ConvolveOpcop=newConvolveOp(newKernel(3,3,data));
returnimage=cop.filter(image,null);
}
//
publicBufferedImagegetSharpen(){
float[]data={0.0f,-0.75f,0.0f,-0.75f,4.0f,-0.75f,0.0f,
-0.75f,0.0f};
ConvolveOpcop=newConvolveOp(newKernel(3,3,data));
returnimage=cop.filter(image,null);
}
//11)
publicBufferedImagegetRotate(){
AffineTransformOpatop=newAffineTransformOp(
AffineTransform.getRotateInstance(Math.PI,
image.getWidth()/2,image.getHeight()/2),
AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
returnimage=atop.filter(image,null);
}
(){
returnimage;
}
publicstaticvoidmain(String[]args)throwsIOException{
StringfilePath="F:/k7qp5.png";
FileInputStreamfin=newFileInputStream(filePath);
BufferedImagebi=ImageIO.read(fin);
ImageInitflt=newImageInit(bi);
flt.changeGrey();
flt.getGrey();
flt.getBrighten();
bi=flt.getProcessedImg();
Stringpname=filePath.substring(0,filePath.lastIndexOf("."));
Filefile=newFile(pname+".jpg");
ImageIO.write(bi,"jpg",file);
}
}
㈧ 為什麼加上二值化就會有語法上的錯誤
Java程序中的每個變數要麼是基本數據類型(boolean, char, byte, short, int, long, float, double),要麼是對對象的引用
C++有許多種基本類型,額外還有struct, union, enum, 數組和指針,C++指針可以指向對象,也可以不指向對象
Java沒有枚舉、聯合類型,因為Java認為沒有必要。將可有可無的語言元素去掉是Java對C/C++做出的一大改變,因此,普遍認為Java較C++更輕便,更精簡
Java採用Unicode字元集,C++通常用ASCII字元集。但ASCII是Unicode的子集,對於習慣於ASCII的程序員感覺不到區別
Java中的boolean類型不能轉換成其他類型,反之亦然。C++最近引進了bool類型,代表布爾類型,整型也作為邏輯判斷
模板是一種「泛型編程思想」,它有別於「面向對象編程思想」。C++在很大程度上已經支持了這種新型編程方法,特別是STL的出現
Java目前仍未支持泛型編程,不過據說Sun公司有在Java中引入模板的計劃
C++支持「運算符的重載」,這是它的一個很重要的多態特徵,是數據抽象和泛型編程的利器。它允許直接對對象進行四則運算,正像基本數據類型那樣
Java不支持這種多態機制,也是為降低復雜性
兩種語言都支持方法重載(overloading)
在C++中,為了允許運行時動態決定哪個函數被調用,一個函數必須用virtual修飾。virtual關鍵字被自動繼承,用以支持多態
凡是沒有用virtual修飾的成員函數(包括static)都是靜態綁定的,即在編譯時決定調用哪個版本
而在Java中,除了static、final、private是靜態綁定以外,所有方法一律按動態綁定處理
C++中有「拷貝構造函數」的概念,在三種情況下,自動調用它
用一個對象初始化另一對象
對象作實參進行函數調用
對象作函數的返回值
通常,當一個對象需要做「深拷貝」(錢能:《C++程序設計教程》)時,我們需要為它事先定義「拷貝構造函數」、「賦值運算符的重載函數」和「析構函數」;否則編譯器將以「按位」的形式自動生成相應的預設函數。倘若類中含有指針成員或引用成員,那麼這三個默認的函數就隱含了錯誤
Java則沒有這種語法結構和語義邏輯
C++支持inline函數,可以避免函數的堆棧調用,提高運行效率
Java無這種語義
C++中,構造函數的初始化列表是這樣使用的:首先按繼承順序調用基類的構造函數構造基類對象,然後按聲明順序調用成員對象的構造函數構造成員對象,最後對列表中出現的成員變數做初始化
Java不採用初始化列表這種構造機制
它們的構造順序基本一致:
靜態變數初始化
靜態初始化塊(Java)
調用基類的構造函數構造基類對象
實例變數的初始化
構造函數的其餘部分
Java使用abstract關鍵字修飾抽象方法或抽象類
C++的對等語法是「純虛函數」和「抽象類」
兩者都使用抽象類作為繼承層次中的基類,提供一般概念,由子類實現其抽象方法,且抽象類都不能被直接實例化為對象
Java中有final關鍵字,修飾類、方法或變數
final類不能被繼承
final方法不能被子類覆蓋
final變數就是常量
C++中沒有這個關鍵字,常量可以使用const或#define定義
const還可以修飾成員函數,即「常成員函數」,當一個const成員函數修改成員數據,或調用非const成員函數時,編譯器會報錯
我們應將不修改成員數據的函數聲明為const
Java和C++中的static關鍵字語法和語義基本相同
static成員變數又叫類變數,被類的所有對象共享
A::x (C++):必須在類體外初始化
A.x (Java):必須在類體內初始化
static成員方法又叫類方法,訪問static變數
A::f( ) (C++)
A.f( ) (Java)
兩者都有內部類和局部類的語法和語義
Java中沒有友元函數和友元類的概念,嚴格支持封裝,不允許外部方法訪問類的私有成員
而C++支持friend關鍵字,允許外部方法訪問類的私有成員,因此不是一種純面向對象的編程語言
Java中類或interface可以用public修飾,也可以不修飾;而C++類不能修飾
三種訪問許可權的語義相同,語法略有差別
C++中還有繼承許可權修飾符,Java則沒有
class A: protected B, public C (C++)
class A extends B (Java)
Java有super關鍵字,指代父類對象,通常被用於調用父類的構造方法或一般方法
C++則沒有super關鍵字
兩者都有this,指代當前對象
Java有package的概念,可以將類組織起來,便於打包和部署,也有利於類的安全。C++沒有這個概念,一個類可以被任意類訪問
Java applet可以被嵌入HTML文檔中,然後由Web瀏覽器下載和執行
Java API有對網路通訊的特別支持
C++則無內置網路功能
C++程序員必須顯式地實現動態內存管理,在析構函數中用delete運算符或free( )函數釋放對象和其他動態分配的數據空間,否則會造成「內存泄露」
而在Java中,垃圾收集是自動的。當對象的最後一個引用變數被釋放掉,這個對象就成為垃圾收集器的候選對象了
因此Java不支持析構函數
finalize( )方法主要被用來釋放先前打開的非內存資源,如文件句柄
Java源代碼被編譯成位元組碼(.class文件),位元組碼是一種只有JVM才能識別的二進制低級代碼,它與具體的處理器無關,要由安裝在OS之上的JVM解釋執行,轉換成相應平台的機器碼,因此Java是體系結構中立和跨平台的
而C++直接被編譯成底層平台的二進制機器碼,由CPU執行,是平台相關的
因此,當解釋執行時,Java程序速度更慢
Java語言支持多線程,允許並發線程的同步與互斥操作
C++則沒有這種內在機制
㈨ 關於java處理圖像佔用空間大的相關問題~~
看你的圖像的色彩模型,
如果是RGB每個像素24bit,3個位元組,佔用1024*1024*3=3MiB內存
如果ARGB,一般都是每個像素32bit,4個位元組,佔用1024*1024*4=4MiB內存(Java也常用這個交換)
如果灰度模型,每個像素8bit,佔用1MiB內存
如果2值化,每個像素1bit,佔用1024*1024/8=128KiB內存,這在無壓縮情況下容量最小。
常見視頻I420模型,每個像素6bit,1024*1024能用768KiB獲得近似真彩的效果.
圖像處理在內存中就是這樣,如果想空間小,就要增加運算時間使用壓縮演算法和調整色彩模型。