မိတ္ေဆြ၊ ညီအစ္ကို၊ ေမာင္ႏွမမ်ား အားလံုးပဲ မဂၤလာပါဗ်ာ။ ဒီေန႔ေတာ့ က်ေနာ္တို႔ Visual Studio C# ကို အသံုးျပဳၿပီး Color Image တစ္ခုကို Grayscale Image ပံုစံသို႔ ဘရ္လိုေျပာင္းလဲ ယူႏိုင္မလဲဆိုတာေလးနဲ႔ ပါတ္သတ္ၿပီး ေလ့လာၾကည့္ပါ့မရ္။ က်ေနာ့္ ေလ့က်င့္ခန္းေတြကေတာ့ စတင္ ေလ့လာသူမ်ားအတြက္သာ ရည္ရြယ္ပါတရ္။ ဒါေၾကာင့္ သိေနၿပီးသား သူမ်ားအေနနဲ႔ နားလည္ေပးၾကဖို႔နဲ႔ က်ေနာ္ရဲ႕ တင္ျပပံု မွားယြင္းတာမ်ားရွိခဲ့ရင္ ျပန္လည္ေထာက္ျပေပးႏိုင္ဖို႔ ေမွ်ာ္လင့္ပါတရ္ဗ်။
ေရွ႕ Black & White ေျပာင္းတဲ့ ေလ့က်င့္ခန္းမွာေတာ့ Grayscale Image နဲ႔ Black & White Image ကြဲျပားတရ္ဆိုတာကို က်ေနာ္ မွတ္ခ်က္ကေလးနဲ႔ ေျပာခဲ့ပါတရ္။ တခ်ိဳ႕က Grayscale Image ကို Black & White Image လို႔ မွားေခၚတတ္ၾကလို႔ပါ။ Black & White Image ဆုိတာက Image တစ္ခုလံုးမွာ အျဖဴ၊ အမဲ Color ႏွစ္မ်ိဳးတည္းနဲ႔ ဖြဲ႔စည္းထားတဲ့ Image ကိုဆိုလိုတာပါ။ Grayscale ကေတာ့ ဒီလိုမဟုတ္ပါဘူး။ Pixel တစ္ခုထဲမွာေတာ့ RGB တူညီတဲ့ Color range ရွိရပါ့မရ္။ Pixel တစ္ခုနဲ႔ တစ္ခုကေတာ့ Color range တူစရာမလိုပါဘူး။ ဥပမာအေနနဲ႔...
first_Pixel = RBG(2, 2, 2);
second_Pixel = RGB(241, 241, 241);
-----
-----
Last_Pixel = RGB(126, 126, 126);
စသည္ျဖစ္ေပါ့။ Color range အနည္း၊ အမ်ားေပၚမူတည္ၿပီး light gray and dark gray ဆိုၿပီး Pixel တစ္ခုနဲ႔တစ္ခု ကြာသြားပါလိမ့္မရ္။ Image တစ္ခုကို Grayscale ေျပာင္းလဲတဲ့အခါမွာေတာ့ က်ေနာ္တို႔ နည္းလမ္း(၃)ခုကိုအသံုးျပဳႏိုင္ပါတရ္။ ၄င္း နည္းလမ္းေတြကေတာ့...
Grayscale (Average Method)
Grayscale (Lightness Method)
Grayscale (Luminosity Method)
တို႔ပဲျဖစ္ပါတရ္။
Average Method // AverageColor = (R + G + B) / 3;
ဒီ Method ကေတာ့ ရိုးရွင္းပါတရ္။ Pixel တစ္ခုကို Detect လုပ္ၿပီး R, G, B Color Value ေတြကို ဆြဲထုတ္ပါတရ္။ ေနာက္ ၄င္း R, G, B Color သံုးခုကိုေပါင္းၿပီး အေရအတြက္နဲ႔ ျပန္စားကာ Average Color တန္ဖိုးကို တြက္ယူပါတရ္။ ေနာက္ဆံုးအဆင့္အေနနဲ႔ ရရွိလာတဲ့ Average Color တန္ဖိုးကို Pixel ရဲ႕ မူလ R, G, B Color တန္ဖိုးေတြ ေနရာမွာ အစားထိုးလိုက္တာပါ။ ဒီနည္းအတိုင္း last Pixel အထိ အလုပ္လုပ္ၿပီး Grayscale Image တစ္ခုအျဖစ္ ေျပာင္းလဲယူလိုက္ တာပဲျဖစ္ပါတရ္။
Lightness Method // LightnessColor = (Max(R, G, B) + Min(R, G, B)) / 2;
ဒီေကာင္ကေတာ့ ပထမဦးဆံုး Pixel တစ္ခုကို Detect လုပ္ၿပီး R, G, B Color Value ေတြကိုဆြဲထုတ္ပါတရ္။ ေနာက္ ၄င္း R, G, B Color Value ေတြထဲကမွ Maximun ကိန္းနဲ႔ Minimum ကိန္းကို ရွာပါတရ္။ ေနာက္တစ္ဆင့္မွာေတာ့ ၄င္း Max and Min ကိန္းႏွစ္လုံးကိုေပါင္းၿပီး 2 နဲ႔ျပန္စားကာ Average Lightness Color ကို တြက္ယူပါတရ္။ ေနာက္ဆံုးအဆင့္အေနနဲ႔ ရရွိလာတဲ့ Average Color တန္ဖိုးကို Pixel ရဲ႕ မူလ R, G, B Color တန္ဖိုးေတြ ေနရာမွာ ျပန္အစားထိုးလိုက္တာပါ။ ဒီနည္းအတိုင္း last Pixel အထိ အလုပ္လုပ္ၿပီး Grayscale Image တစ္ခုအျဖစ္ ေျပာင္းလဲယူလိုက္တာပဲျဖစ္ပါတရ္။
Luminosity Method // LuminosityColor = 0.21 R + 0.72 G + 0.07 B;
ဒီ Mehtod ကလည္း ပထမဦးဆံုး Pixel တစ္ခုကို Detect လုပ္ၿပီး R, G, B Color Value ေတြကိုဆြဲထုတ္ပါတရ္။ ရရွိလာတဲ့ R တန္ဖိုးကို 0.21 နဲ႔ေျမွာက္၊ G တန္ဖိုးကို 0.72 နဲ႔ေျမွာက္၊ B တန္ဖိုးကို 0.07 နဲ႔ေျမွာက္ပါတရ္။ ၿပီးရင္ေတာ့ အားလံုးကို ျပန္ေပါင္းၿပီး Pixel ရဲ႕ မူလ R, G, B Color တန္ဖိုးေတြ ေနရာမွာ ျပန္အစားထိုးလိုက္တာပါ။ ဒီနည္းအတိုင္း last Pixel အထိ အလုပ္လုပ္ခိုင္းၿပီး Grayscale Image တစ္ခုအျဖစ္ ေျပာင္းလဲယူလိုက္တာပဲျဖစ္ပါတရ္။
ကဲ... ဒီေလာက္ဆိုရင္ေတာ့ Grayscale ေျပာင္းလဲယူႏိုင္တဲ့ method သံုးခုကို ၄င္းတို႔ရဲ႕ Formula နဲ႔အတူ သိၿပီ လို႔ ထင္ပါတရ္။ က်ေနာ္တို႔ GUI ေဖာက္ Coding ေရးၿပီး လက္ေတြ႔ေလ့လာၾကည့္ရေအာင္။ ဒါကေတာ့ က်ေနာ္တို႔ Project မွာ အသံုးျပဳမရ္ Library File ေတြပါ။
ဒီေန႔ ေလ့က်င့္ခန္းအတြက္ GUI တည္ေဆာက္ျခင္းအပိုင္းမွာေတာ့ က်ေနာ္ Button(1)ခု၊ PictureBox(2)ခုနဲ႔ comboBox(1)ခုကို အသံုးျပဳထားပါတရ္။ Tools ေတြရဲ႕ Properties ေတြကိုေတာ့ ေအာက္က Table အတိုင္း ျပင္ယူလိုက္ၾကပါဗ်ာ။
က်ေနာ္ကေတာ့ ေအာက္ကပံုအတိုင္း ပံုစံခ်ထားပါတရ္ဗ်ာ။ မိတ္ေဆြတို႔အေနနဲ႔ေတာ့ GUI ကို ႀကိဳက္သလို ပံုေဖာ္ ဖန္တီးႏိုင္ပါတရ္ဗ်။
ဒီေန႔ ေလ့က်င့္ခန္းမွာေတာ့ Grayscale Processing အတြက္ ComboBox ကိုသံုးထားပါတရ္။ ComboBox ရဲ႕ Index အခ်ိန္းအေျပာင္းေပၚမူတည္ၿပီး Grayscale Method ေျပာင္းလဲ လုပ္ေဆာင္သြားမွာျဖစ္ပါတရ္။ ComboBox ကို D-Click ေပးၿပီး ေအာက္က Method ေလးကို ေရးယူလိုက္ပါဗ်ာ။
Method ကိုေတာ့ Processing လုပ္မရ္႕ Image နဲ႔ Method Changing အတြက္ Index Value ကုိ Parameter Passing လုပ္ထားပါတရ္။ Pixel Detection လုပ္တဲ့ လုပ္ငန္းစဥ္ကိုေတာ့ က်ေနာ္တို႔ ေရွ႕မွာေလ့လာခဲ့ၿပီးျဖစ္တဲ့ Fast Image Processing ေလ့က်င့္ခန္းအတိုင္း Detect လုပ္ထားပါတရ္။ နားမလည္ေသးတဲ့ မိတ္ေဆြတို႔အတြက္ ေရွ႕သင္ခန္းစာေတြကို ျပန္ဖတ္ေပးပါလို႔ တိုက္တြန္းပါရေစ။ Average, Lightness, Luminosity Method ေတြရဲ႕ အလုပ္လုပ္ပုံကိုေတာ့ က်ေနာ္ အေပၚမွာ အေသစိတ္ရွင္းျပခဲ့ပါတရ္။ Coding မွာ ခက္ခဲတာ ဘာမွမပါလို႔ နားလည္ၾကလိမ့္မရ္လို႔ ေမွ်ာ္လင့္ပါတရ္ဗ်။
ဒါကေတာ့ Calling Method ပံုစံပါ။ if()statement နဲ႔စစ္ထားတာကေတာ့ Processing လုပ္မရ္႕ Image ကုိဆြဲတင္ၿပီး ရွိ/မရွိနဲ႔ ComboBox မွာ Processing လုပ္မရ္႔ Method ကို ေရြးခ်ယ္ၿပီးသား ရွိ/မရွိကို သိခ်င္လို႔ပါ။
မိတ္ေဆြတို႔ အားလံုးကို ၿခံဳငံုနားလည္သြားေအာင္ ေအာက္မွာ Coding အျပည့္အစံုကို ေလ့လာႏိုင္ပါတရ္ဗ်။
မိတ္ေဆြ၊ ညီအစ္ကို၊ ေမာင္ႏွမအားလံုး ေလ့လာျခင္းျဖင့္ ေက်နပ္ႏိုင္ၾကပါေစ။
မိတ္ေဆြ၊ ညီအစ္ကို၊ ေမာင္ႏွမမ်ား အားလံုးပဲ မဂၤလာပါဗ်ာ။ ဒီေန႔ေတာ့ က်ေနာ္တို႔ Visual Studio C# ကို အသံုးျပဳၿပီး Color Image တစ္ခုကို Black & White ပံုစံသို႔ ဘရ္လိုေျပာင္းလဲ ယူႏိုင္မလဲဆိုတာေလးနဲ႔ ပါတ္သတ္ၿပီး ေလ့လာၾကည့္ပါ့မရ္။ က်ေနာ့္ ေလ့က်င့္ခန္းေတြကေတာ့ စတင္ ေလ့လာသူမ်ားအတြက္သာ ရည္ရြယ္ပါတရ္။ ဒါေၾကာင့္ သိေနၿပီးသား သူမ်ားအေနနဲ႔ နားလည္ေပးၾကဖို႔နဲ႔ က်ေနာ္ရဲ႕ တင္ျပပံု မွားယြင္းတာမ်ားရွိခဲ့ရင္ ျပန္လည္ေထာက္ျပေပးႏိုင္ဖို႔ ေမွ်ာ္လင့္ပါတရ္ဗ်။
က်ေနာ္တို႔ ဒီေန႔ ေလ့က်င့္ခန္းေလးကို မေလ့လာမွီ Ditigal Image တစ္ခုရဲ႕ အၾကမ္းဖ်ဥ္း ဖြဲ႔စည္းပံုနဲ႔ သေဘာတရားကို ၾကည့္မရ္ဆိုရင္ သိခဲ့ၿပီးသားအတိုင္းပါပဲ... Image တစ္ခုဟာ 2-Dimension ပံုစံ Pixel ေတြနဲ႔ ဖြဲ႔စည္းထားပါတရ္။ Pixel တစ္ခုစီတိုင္းမွာေတာ့ အေျခခံအက်ဆံုး Red, Green, Blue and Alpha ဆိုတဲ့ Color တန္ဖိုးေတြရွိပါတရ္။ ဒီ Color တန္ဖိုး အခ်ိန္းအေျပာင္းေပၚမူတည္ၿပီး Pixel တစ္ခုစီတိုင္းမွာ Secondly Color တစ္ခုစီျဖစ္လာၿပီး ရုပ္လံုးေပၚကာ က်ေနာ္တို႔ ျမင္ကြင္းထဲကို ေရာက္လာတာပဲျဖစ္ပါတရ္။ ယင္းဆိုရင္ျဖင့္ Pixel တစ္ခုစီတိုင္းမွာရွိတဲ့ Color တန္ဖိုးေတြကို Black သို႔မဟုတ္ White အျဖစ္ ေျပာင္းလဲေပးႏိုင္မွသာ က်ေနာ္တို႔ လိုခ်င္ေနတဲ့ Black & White Image တစ္ခုကို ရရွိပါလိမ့္မရ္။
ဒီေတာ့ က်ေနာ္တို႔အေနနဲ႔ RGB Color Channel ရဲ႕ ဘရ္တန္ဖိုးေတြက Black ျဖစ္တရ္၊ ဘရ္တန္ဖိုးေတြက White ျဖစ္မရ္ဆုိတာကို သိဖို႔လိုအပ္လာပါၿပီ။ မခက္ခဲပါဘူးဗ်ာ။ Color တန္ဖိုးရဲ႕ lower bound ျဖစ္တဲ့ Zero(0) ဟာ Black Color ျဖစ္ၿပီး upper bound ျဖစ္တဲ့ 255 ဟာ White Color ျဖစ္ပါတရ္ (Color Channel တစ္ခုဟာ 0 to 255 ရွိတရ္ဆိုတာေတာ့ သိၾကမရ္ထင္ပါတရ္)။ ဆိုလိုတာကေတာ့ RBG(0, 0, 0) ဟာ Black Color ျဖစ္တရ္။ RGB(255, 255, 255) ဟာ White Color ျဖစ္တရ္လို႔ ေျပာတာပါ။
ကိုရင္ေမာင္ေရ... Color တန္ဖိုးေတြကို Black(0) ျဖစ္ျဖစ္၊ White(255) ျဖစ္ျဖစ္ ေျပာင္းလဲရမွာေတာ့ ဟုတ္ပါၿပီ။ Pixel ကို Detect လုပ္တဲ့အခါမွာ 0 to 255 ၾကား ဘာျဖစ္လာမရ္မွန္းမသိတဲ့ Color တန္ဖိုးေတြ ရမွာေလ။ ဒါကို က်ေနာ္တို႔က ဘရ္ဟာကို Black ေျပာင္းၿပီး ဘရ္ဟာကို White ေျပာင္းယူမွာလဲလို႔ ေမးဖို႔ရွိလာပါတရ္။ ဒီအေမးကိုေတာ့ က်ေနာ္တို႔အေနနဲ႔... ဒီ Algorithm အတြက္ တိတိက်က် သတ္မွတ္ထားတာမရွိပါဘူး။ User ရဲ႕ လိုအပ္ခ်က္အရ Threshold value တစ္ခုထားၿပီး ပိုင္းျခားလိုက္ပါလို႔ ေျဖရမွာပါပဲ။ Threshold Value ဆိုလို႔ ေခါင္းရႈပ္မသြားပါနဲ႔။ 0 to 255 ၾကား တန္ဖိုးတစ္ခုခုကို key အျဖစ္ အေသယူလိုက္တာပါ။ Detect ရရွိတဲ့ တန္ဖိုးဟာ ယင္း key နဲ႔ငယ္ရင္ Black ေျပာင္း၊ ႀကီးရင္ White အျဖစ္ေျပာင္းပါလို႔ ခိုင္းလိုက္တာပါ။ အမ်ားစုကေတာ့ Color Rage (0 to 255) ရဲ႕ တ၀တ္ျဖစ္တဲ့ 127 ကို Threshold Value ထားၿပီး Black & White Image အျဖစ္ ေျပာင္းယူၾကပါတရ္။ နားလည္ၾကမရ္ ထင္ပါတရ္ဗ်။
ကဲ... က်ေနာ္တို႔ Processing ရဲ႕ သေဘာတရားကို သိၿပီဆိုရင္ေတာ့ GUI ေလးေဖာက္ၿပီး Coding ေလးနဲ႔ လက္ေတြ႔ ေလ့လာၾကည့္ၾကရေအာင္။ ဒါကေတာ့ က်ေနာ္တို႔ Project မွာ အသံုးျပဳမရ္ Library File ေတြပါ။
ဒီေန႔ ေလ့က်င့္ခန္းအတြက္ GUI တည္ေဆာက္ျခင္းအပိုင္းမွာေတာ့ က်ေနာ္ Button(1)ခု၊ Label(1)ခု၊ PictureBox(2)ခုနဲ႔ TrackBar(1)ခုကို အသံုးျပဳထားပါတရ္။ Tools ေတြရဲ႕ Properties ေတြကိုေတာ့ ေအာက္က Table အတိုင္း ျပင္ယူလိုက္ၾကပါဗ်ာ။
က်ေနာ္ကေတာ့ ေအာက္ကပံုအတိုင္း ပံုစံခ်ထားပါတရ္ဗ်ာ။ မိတ္ေဆြတို႔အေနနဲ႔ေတာ့ GUI ကို ႀကိဳက္သလို ပံုေဖာ္ ဖန္တီးႏိုင္ပါတရ္ဗ်။
ဒီေန႔ ေလ့က်င့္ခန္းမွာေတာ့ Black & White Processing အတြက္ သီးသန္႔ Button မထည့္ေတာ့ပဲ TrackBar ရဲ႕ Scroll_Event ထဲက တိုက္ရိုက္ Processing လွမ္းလုပ္တဲ့ ပံုစံေလးနဲ႔ ေလ့လာၾကည့္သြားပါ့မရ္။ ဒီေတာ့ TrackBar Value ေျပာင္းလဲမႈရွိတိုင္း Black & White Processing ေျပာင္းလဲမႈျဖစ္မွာ ျဖစ္ပါတရ္။ TrackBar ကို D-Click ေပးၿပီး ေအာက္က Method ေလးကို ေရးယူလိုက္ပါဗ်ာ။
Method ကိုေတာ့ Processing လုပ္မရ္႕ Image နဲ႔ Threshold Value ကုိ Parameter Passing လုပ္ထားပါတရ္။ Pixel Detection လုပ္တဲ့ လုပ္ငန္းစဥ္ကိုေတာ့ က်ေနာ္တို႔ ေရွ႕မွာေလ့လာခဲ့ၿပီးျဖစ္တဲ့ Fast Image Processing ေလ့က်င့္ခန္းအတိုင္း Detect လုပ္ထားပါတရ္။ နားမလည္ေသးတဲ့ မိတ္ေဆြတို႔အတြက္ ေရွ႕သင္ခန္းစာေတြကို ျပန္ဖတ္ေပးပါလို႔ တိုက္တြန္းပါရေစ။ ဒီမွာ Black & White အတြက္ ထူးျခားသြားတာကေတာ့ Pixel တစ္ကြက္ခ်င္းစီမွာ ရွိေနတဲ့ R, G, B Color တန္ဖုိး(၃)ခုကို ေပါင္းၿပီး အေရအတြက္နဲ႔ ျပန္စားကာ Average Color တန္ဖိုးကို ရွာယူလိုက္တာပါပဲ။ က်န္တာကေတာ့ က်ေနာ္ အေပၚမွာ ေဆြးေႏြးခဲ့ၿပီးတဲ့အတိုင္းပဲ ရလာတဲ့ averageColor တန္ဖိုးကို Threshold Value နဲ႔ ႏႈိင္းယွဥ္ပါတရ္။ averageColor ကႀကီးေနရင္ ယင္း Pixel ကြက္ရဲ႕ R, G, B Color တန္ဖိုးေတြကို 255 ေတြေပးၿပီး အျဖဴေရာင္ Pixel ကြက္အျဖစ္ေျပာင္းလဲယူပါတရ္။ ငယ္ခဲ့ရင္ေတာ့ 0 ေတြေပးၿပီး အနက္ေရာင္ Pixel ကြက္အျဖစ္ ဖန္တီးယူလိုက္တာပါ။ အရမ္း ရိုးရွင္းၿပီး လြယ္ကူလြန္းပါတရ္။
ဒါကေတာ့ Calling Method ပံုစံပါ။ ဘရ္ေလာက္ Threshold Value နဲ႔ Processing လုပ္ထားတရ္ဆိုတာကို ျပဖို႔ Label ကိုသံုးထားပါတရ္။ if()statement နဲ႔စစ္ထားတာကေတာ့ Processing လုပ္မရ္႕ Image ကုိဆြဲတင္ၿပီး ရွိ/မရွိကို သိခ်င္လို႔ပါ။
မိတ္ေဆြတို႔ အားလံုးကို ၿခံဳငံုနားလည္သြားေအာင္ ေအာက္မွာ Coding အျပည့္အစံုကို ေလ့လာႏိုင္ပါတရ္ဗ်။
မိတ္ေဆြ၊ ညီအစ္ကို၊ ေမာင္ႏွမအားလံုး ေလ့လာျခင္းျဖင့္ ေက်နပ္ႏိုင္ၾကပါေစ။
မိတ္ေဆြ၊ ညီအစ္ကို၊ ေမာင္ႏွမမ်ား အားလံုးပဲ မဂၤလာပါဗ်ာ။ ဒီေန႔ေတာ့ က်ေနာ္တို႔ Visual Studio C# ကို အသံုးျပဳၿပီး Image တစ္ခုကို Rotate and Flip ပံုစံအမ်ိဳးမ်ိဳးနဲ႔ ဘရ္လိုဆြဲယူ ၾကည့္ႏိုင္မလဲဆိုတာေလးန႔ဲ ပါတ္သတ္ၿပီး ေလ့လာၾကည့္ပါ့မရ္။ နည္းလမ္းေပါင္းစံု ရွိတဲ့အထဲကေနၿပီ အလြရ္ကူဆံုးနည္းလမ္းျဖစ္တဲ့ System.Drawing; ေအာက္က RotateFlip()Method ကိုအသံုးျပဳၿပီး ဖန္တီးယူႏိုင္တာေလးကို ေလ့လာၾကည့္ပါ့မရ္။ က်ေနာ့္ ေလ့က်င့္ခန္းေတြကေတာ့ စတင္ ေလ့လာသူမ်ားအတြက္သာ ရည္ရြယ္ပါတရ္။ ဒါေၾကာင့္ သိေနၿပီးသား သူမ်ားအေနနဲ႔ နားလည္ေပးၾကဖို႔နဲ႔ က်ေနာ္ရဲ႕ တင္ျပပံု မွားယြင္းတာမ်ားရွိခဲ့ရင္ ျပန္လည္ေထာက္ျပေပးႏိုင္ဖို႔ ေမွ်ာ္လင့္ပါတရ္ဗ်။ က်ေနာ္တို႔ အသံုးျပဳႏိုင္တဲ့ RotateFlipType (16)မ်ိဳးရွိပါတရ္။ ရွင္းလင္းခ်က္ေတြကိုေတာ့ ေအာက္က Table မွာ ၾကည့္ႏိုင္ပါတရ္။
Drawing Library က အသင့္ေပးထားတဲ့ Method ကိုေခၚသံုးမွာျဖစ္လို႔ ဒီေန႔ ေလ့က်င့္ခန္းက လြရ္တရ္လို႔ ထင္ရပါလိမ့္မရ္။ ဒါေပမရ္႕ Image Control and Processing ဘက္ကို ေလ့လာေနတဲ့ သူေတြအတြက္ တစ္ဘက္တစ္လမ္းက အေထာက္အကူျဖစ္ႏိုင္လိမ့္မရ္လို႔ေတာ့ ထင္ပါတရ္။ ေနာက္ပိုင္း အဆင့္ျမင့္သင္ခန္းစာေတြၾကရင္ေတာ့ ဒီ Flip and Rotation Method ေတြကို ကိုယ္တိုင္ ဘရ္လိုဖန္တီးယူႏိုင္မလဲဆိုတာနဲ႔ ပါတ္သတ္ၿပီး Graphic နဲ႔ျဖစ္ေစ၊ Pixel Detection ပံုစံနဲ႔ျဖစ္ေစ က်ေနာ္ ထပ္ေဆြးေႏြးေပးပါ့မရ္ဗ်။ ဒီေန႔ေတာ့ သေဘာတရားနဲ႔ Result ကို ကၽြမ္း၀င္သြားေအာင္ လြရ္လြရ္ကူကူပဲ ေလ့လာၾကည့္ၾကပါ့မရ္။
ဒါကေတာ့ က်ေနာ္တို႔ Project မွာ အသံုးျပဳမရ္ Library File ေတြပါ။
ဒီေန႔ ေလ့က်င့္ခန္းအတြက္ GUI တည္ေဆာက္ျခင္းအပိုင္းမွာေတာ့ က်ေနာ္ Button(1)ခု၊ PictureBox(2)ခုနဲ႔ ComboBox(1)ခုကို အသံုးျပဳထားပါတရ္။ Tools ေတြရဲ႕ Properties ေတြကိုေတာ့ ေအာက္က Table အတိုင္း ျပင္ယူလိုက္ၾကပါဗ်ာ။
က်ေနာ္ကေတာ့ ေအာက္ကပံုအတိုင္း ပံုစံခ်ထားပါတရ္ဗ်ာ။ မိတ္ေဆြတို႔အေနနဲ႔ေတာ့ GUI ကို ႀကိဳက္သလို ပံုစံေဖာ္ႏိုင္ပါတရ္။
ဒီေန႔ ေလ့က်င့္ခန္းကိုေတာ့ အဆင့္(၃)ဆင့္နဲ႔ ေလ့လာၾကည့္ပါ့မရ္။ ပထမအဆင့္ကေတာ့ Form_Load မွာ System.Drawing; Library ေအာက္မွာ Enumation အေနနဲ႔ ရွိေနၿပီးသား RotateFlipType ေတြကို ComboBox ထဲသို႔ ဆြဲတင္ယူမွာျဖစ္ပါတရ္။ ဒီအတြက္ LoadFlipType() Method ဖန္တီးပံုေလးနဲ႔ Form_Load မွာေခၚယူပံုေလးကို ေအာက္မွာ ေလ့လာၾကည့္ပါ့မရ္။
LoadFlipType()Method မွာေတာ့ Parameter အျဖစ္ ComboBox ကို Passing လုပ္ထားပါတရ္။ Coding စစခ်င္းမွာ Enum.GetNames() Method ကိုအသံုးျပဳၿပီး System.Drawing; Libray ထဲက Enumation Type အေနနဲ႔ သိမ္းထားေသား RotateFlipType ေတြကို Scan ဖတ္ယူပါတရ္(ဒီနည္းအတိုင္းပဲ အျခားေသာ Enumation Type ေတြကိုလည္း ဆြဲယူႏုိင္ပါတရ္ဗ်)။ ဒီမွာ Array တစ္ခုခုထဲကို ထည့္ထားလို႔ရပါတရ္။ က်ေနာ္ကေတာ့ var Type ကိုသံုးထားပါတရ္။ ေနာက္တစ္ေၾကာင္းမွာေတာ့ Scan ဖတ္လို႔ရရွိလာတဲ့ Flip Type ေတြကို Loop ပါတ္ၿပီး string Data ေတြအျဖစ္ ComboBox ထဲသို႔ Add လိုက္တာပဲျဖစ္ပါတရ္။ အေပၚက Form_Load ရဲ႕ Calling Method မွာေတာ့ က်ေနာ္တို႔ Flip Type ေတြကို ေဖာ္ျပေစခ်င္တဲ့ ComboBox ကို Parameter ေခၚေပးလိုက္ယံုပါပဲဗ်။ ဒါဆိုရင္ေတာ့ Form_Load တတ္ၿပီးတဲ့အခ်ိန္မွာ ေအာက္ကပံုအတိုင္း ComboBox ထဲမွာ Flip Type ေတြေရာက္ေနတာ ေတြ႔ရပါလိမ့္မရ္။
ခက္ခက္ခဲခဲမပါလို႔ နားလည္ၾကလိမ့္မရ္လို႔ ထင္ပါတရ္ဗ်။ ဒုတိယအဆင့္ကို ဆက္ေလ့လာၾကည့္ပါ့မရ္။ ဒီအဆင့္ကေတာ့ picOriginalImg PictureBox ထဲသို႔ Image ဆြဲတင္တဲ့အပိုင္းပါ။ PictureBox ထဲသို႔ Image ဆြဲတင္တာကိုေတာ့ ေရွ႕မွာ ေလ့လာခဲ့ၿပီးျဖစ္ၾကတဲ့ ေလ့က်င့္ခန္းတိုင္းမွာ ပါေနလို႔ က်ေနာ္အေသးစိတ္မရွင္းေတာ့ပါဘူး။
ေနာက္ဆံုးအဆင့္ကေတာ့ ComboBox ရဲ႕ Index Change မွာ ေရြးခ်ယ္လိုက္တဲ့ Action အေပၚမူတည္ၿပီး Flip and Rotation Process ကိုလုပ္ၿပီး picResultImg PictureBox မွာ ေဖာ္ျပေပးဖို႔ပါ။ ဒီအတြက္ cbFlipType ComboBox ကို D_Click ေပးၿပီး SelectedIndexChanged Event မွာ ေအာက္ပါ Calling ပံုစံနဲ႔ Method ခြဲေရးတဲ့ပံုစံေလးကို ေရးယူလုိက္ပါဗ်ာ။
Calling Method ပံုစံကေတာ့ ရွင္းပါတရ္။ စစခ်င္းမွာ if()statement နဲ႔ Processing လုပ္ခ်င္တဲ့ Image ဆြဲတင္ၿပီးသား ရွိ/မရွိကို စစ္ပါတရ္။ Image Loading မလုပ္ရေသးဘူးဆိုရင္ေတာ့ FlipImage()Method ကို လွမ္းေခၚမွာ မဟုတ္ပါဘူးဗ်။ Image လည္း Loading ရွိၿပီ၊ ComboBox မွာလည္း Action တစ္ခုခုကို ေရြးၿပီဆိုရင္ေတာ့ ေအာက္က FlipImage()Method ကို လွမ္းေခၚပါလိမ့္မရ္။
FlipImage()Method မွာေတာ့ Parameter အျဖစ္ Image တစ္ခုနဲ႔ string တစ္ခုကို Passing လုပ္ထားပါတရ္။ ပထမ parameter ကေတာ့ processing လုပ္ခ်င္တဲ့ Image ပါ။ ဒုတိယကေတာ့ ေျပာင္းလဲယူခ်င္တဲ့ Rotate and Flip Type ေပါ့။ အတြင္းပိုင္း အလုပ္လုပ္သြားတဲ့ ပံုစံကေတာ့ က်ေနာ္တို႔ ေလ့လာေနၾက ပံုစံအတိုင္းပါပဲ။ ေရာက္လာတဲ့ Image ကို Bitmap အျဖစ္ Clone ပြားယူပါတရ္။ ဒုတိယ cmd line ကေတာ့ string အေနနဲ႔ ပို႔လိုက္တဲ့ RotateFlipType စာသားကို RotateFlip()Method ကနားလည္တဲ့ RotateFlipType အျဖစ္ ေျပာင္းလဲယူတာပါ။ ရွင္းျပရခက္တရ္ဗ်။ ဒါေပမဲ့ ၾကည့္လိုက္တာနဲ႔ နားလည္ၾကမရ္ ထင္ပါတရ္။ ဒီအဆင့္ကို ေရာက္ၿပီဆိုရင္ေတာ့ String အေနနဲ႔ Passing ၀င္လာတဲ့ RotateFlipType ေတြဟာ RotateFlip()Method ကနားလည္တဲ့ RotateFlipType အစစ္ျဖစ္သြားပါၿပီ။ ဒါဆိုရင္ေတာ့ တတိယ cmd line အတိုင္း က်ေနာ္တို႔ Clone ပြားယူထားေသာ Image ကို RotateFlip() Method ကိုအသံုးျပဳၿပီး Processing လုပ္ေပးပါလို႔ ခိုင္းလိုက္ယံုပါပဲ။ ေနာက္ဆံုးအဆင့္ကေတာ့ Processing လုပ္ၿပီသား Image ကို ျပန္လည္ေဖာ္ေျပေပးႏိုင္ရန္ Call Method ဆီသို႔ Return ျပန္ေပးလိုက္တာပဲ ျဖစ္ပါတရ္ဗ်ာ။ ပံုမွာ က်ေနာ္ ဥပမာအေနနဲ႔ Rotate180FlipY ဆိုၿပီး ေျပာင္းျပထားပါတရ္ဗ်။
ပိုၿပီးနားလည္သြားေအာင္ Coding အျပည့္အစံုကို ေအာက္မွာ ေလ့လာၾကည့္လိုက္ၾကပါအံုးဗ်ာ။
မိတ္ေဆြ၊ ညီအစ္ကို၊ ေမာင္ႏွမအားလံုး ေလ့လာျခင္းျဖင့္ ေက်နပ္ႏိုင္ၾကပါေစ။
မိတ္ေဆြ၊ ညီအစ္ကို၊ ေမာင္ႏွမမ်ား အားလံုးပဲ မဂၤလာပါဗ်ာ။ ဒီေန႔ေတာ့ က်ေနာ္တို႔ Visual Studio C# ကို အသံုးျပဳၿပီး Image တစ္ခုကို ZoomIn, ZoomOut ပံုစံျဖစ္ ဘရ္လိုဆြဲယူ ၾကည့္ႏိုင္မလဲဆိုတာေလးနဲ႔ ပါတ္သတ္ၿပီး ေလ့လာၾကည့္ပါ့မရ္။ နည္းလမ္းေပါင္းစံု ရွိတဲ့အထဲကေနၿပီ အလြရ္ကူဆံုးနည္းလမ္းျဖစ္တဲ့ Graphic ဆြဲၿပီး ဖန္တီးယူတဲ့ နည္းလမ္းကိုပဲ အသံုးျပဳၿပီး ေလ့လာၾကည့္ပါ့မရ္။ က်ေနာ့္ ေလ့က်င့္ခန္းေတြကေတာ့ စတင္ ေလ့လာသူမ်ားအတြက္သာ ရည္ရြယ္ပါတရ္။ ဒါေၾကာင့္ သိေနၿပီးသား သူမ်ားအေနနဲ႔ နားလည္ေပးၾကဖို႔နဲ႔ က်ေနာ္ရဲ႕ တင္ျပပံု မွားယြင္းတာမ်ားရွိခဲ့ရင္ ျပန္လည္ေထာက္ျပေပးႏိုင္ဖို႔ ေမွ်ာ္လင့္ပါတရ္ဗ်။
ဒါကေတာ့ က်ေနာ္တို႔ Project မွာ အသံုးျပဳမရ္ Library File ေတြပါ။
ဒီေန႔ ေလ့က်င့္ခန္းအတြက္ GUI တည္ေဆာက္ျခင္းအပိုင္းမွာေတာ့ က်ေနာ္ Button(1)ခု၊ PictureBox(1)ခု၊ Panel(1)ခု၊ TrackBar(1)ခုနဲ႔ Label(1)ခုကို အသံုးျပဳထားပါတရ္။ Tools ေတြရဲ႕ Properties ေတြကိုေတာ့ ေအာက္က Table အတိုင္း ျပင္ယူလိုက္ၾကပါဗ်ာ။
က်ေနာ္ကေတာ့ ေအာက္ကပံုအတိုင္း ပံုစံခ်ထားပါတရ္ဗ်ာ။ မိတ္ေဆြတို႔အေနနဲ႔ေတာ့ GUI ကို ႀကိဳက္သလို ပံုစံေဖာ္ႏိုင္ပါတရ္။
ဒီေန႔ ေလ့က်င့္ခန္းမွာေတာ့ Zoom Processing အတြက္ သီးသန္႔ Button မထည့္ေတာ့ပဲ TrackBar ရဲ႕ Scroll_Event ထဲက တိုက္ရိုက္ Processing လွမ္းလုပ္တဲ့ ပံုစံေလးနဲ႔ ေလ့လာၾကည့္သြားပါ့မရ္။ ဒီေတာ့ TrackBar Value ေျပာင္းလဲမႈရွိတိုင္း Zoom Processing ေျပာင္းလဲမႈျဖစ္မွာ ျဖစ္ပါတရ္။ Coding ကို တစ္ဆင့္ခ်င္းစီ ေလ့လာၾကည့္မရ္။
ဒါကေတာ့ က်ေနာ္တို႔ Load Image Button ကို အသံုးျပဳၿပီး PictureBox ေပၚသို႔ Image ဆြဲတင္တဲ့ေနရာမွာ Zoom Processing အတြက္ လိုအပ္ခ်က္မ်ားကို Initial သတ္မွတ္ေပးထားတာပါ။ Global Variable အျဖစ္ colneImg ဆိုၿပီး Processing လုပ္ေနစဥ္အတြင္းမွာ Image ကို သိုေလွာင္ရန္ Image Type တစ္ခုကို ဖန္တီးပါတရ္။ ၿပီးရင္ေတာ့ PictureBox ေပၚသို႔ Image ဆြဲတင္ၿပီးတဲ့အခ်ိန္မွာ ၄င္း Variable ထဲသို႔ Clone ပြားယူ Assign လုပ္လိုက္ပါတရ္။ ဆိုလိုတဲ့ သေဘာကေတာ့ ေနာက္ပိုင္း Processing လုပ္ငန္းစဥ္အတြင္း မူရင္း Image ကိုမထိပဲ ယခု Clone ပြားယူထားေသာ Image နဲ႔သာ Processing လုပ္ပါလို႔ ေျပာလိုက္တာပါ။ PictureBox ရဲ႕ Size ကို CloneImg ရဲ႕ Size အတိုင္း ေျပာင္းလဲလိုက္တာ ကေတာ့ ဆြဲတင္လိုက္ေသာ Image ရဲ႕ Width and Height အတိုင္း PictureBox က လိုက္ၿပီး Fixed ျဖစ္သြားေအာင္ပါ။ TrackBar ကို Initial Value = 50 ေပးထားတာကေတာ့ Zoom In/Out အတြက္ TrackBar ကို စမွတ္ 50 မွာ Zero Line ခ်လိုက္တာပါ။ ဒါမွ ကနဦး ဆြဲတင္လိုက္ေသာ Image ဟာ 50(0%)မွာ ေဖာ္ျပၿပီး 50 ေအာက္ငယ္သြားရင္ ဘရ္ေလာက္ % ထိ ZoomOut ျဖစ္သြားလဲဆိုတဲ့ ZoomOut Process လုပ္္ကာ 50 ထက္မ်ားသြားရင္ေတာ့ ဘရ္ေလာက္ % ထိ ZoomIn ျဖစ္သြားလဲဆိုတဲ့ ZoomIn Process ကိုလုပ္ပါလို႔ ခိုင္းလို႔ရမွာပါ။ နားလည္ၾကလိမ့္မရ္လို႔ ေမွ်ာ္လင့္ပါတရ္။
Zoom In/Out Method ကို ဆက္ေလ့လာၾကည့္ပါ့မရ္။ tbZoomValue ကို D_Click ေပးၿပီး TrackBar ရဲ႕ Scroll_Event ထဲမွာ ေအာက္ပါ Coding ကိုေရးယူလိုက္ပါဗ်ာ။
အနည္းငရ္ရွင္းျပပါ့မရ္။ စစခ်င္းမွာ if()Statement နဲ႔ Zoom Processing လုပ္ခ်င္တဲ့ Image ကို PictureBox ေပၚသို႔ ဆြဲတင္ၿပီးသား ရွိ/မရွိ တနည္းအားျဖင့္ Processing လုပ္ဖို႔ Clone Image ရွိ/မရွိ စစ္ေဆးပါတရ္။ Image မဆြဲတင္ရေသးဘူး ဆိုရင္ေတာ့ Zoom Function အလုပ္လုပ္မွာ မဟုတ္ပါဘူးဗ်ာ။ ဒုတိယ cmd line ကေတာ့ ဘရ္ေလာက္ Zoom In/Out ျဖစ္ေနလဲဆိုတဲ့ Information ကို အသံုးျပဳသူကို ျပေစခ်င္လို႔ ထည့္ထားတာပါ။ TrackBar Value က 50 ေအာက္ငရ္ရင္ အႏုတ္တန္ဖိုးျပမွာျဖစ္ၿပီး 50 ထက္ႀကီးရင္ေတာ့ အေပါင္းတန္ဖိုး ျပေပးမွာျဖစ္ပါတရ္။ ေနာက္တစ္ေၾကာင္းမွာေတာ့ if()statement နဲ႔ zoom တန္ဖိုး (သို႔မဟုတ္) TrackBar Value ဟာ 50 နဲ႔ ညီလား၊ ငယ္လားလို႔ ထပ္စစ္ပါတရ္။ Connection မွန္ရင္ေတာ့ Zoom Out Processing အတြက္ ေအာက္က အလုပ္ကို ဆက္လုပ္ပါလိမ့္မရ္။ ဒီမွာေတာ့ Image ရဲ႕ Width and Height ကို ZoomOut ေၾကာင့္ ေျပာင္းလဲသြားေသာ Width and Height အတိုင္း Rebuild ျပန္လုပ္ေပးဖို႔အတြက္ reWidth နဲ႔ reHeight ဆိုၿပီး တြက္ထုတ္ယူထားပါတရ္။ တြက္ခ်က္မႈကိုေတာ့ အေရာင္းဆိုင္ေတြမွာ Discount တြက္တဲ့ ပံုေသနည္းအတိုင္း စဥ္းစားၿပီး တြက္ယူထားတာပါ။ ဥပမာ - က်သင့္ေငြ 1000 က်ေသာ ပစၥည္းတစ္ခုကို 5% Discount ေပးမရ္ဆိုပါစို႔။ ဒါဆို...
Net Amount = က်သင့္ေငြ - ((က်သင့္ေငြ x Discount) / 100);
ဒီ Formula အတိုင္း တြက္ယူႏိုင္ပါတရ္။ ဒီေတာ့...
Net Amount = 1000 – ((1000 x 5) /100); = 950 က်ပ္ က်သင့္မွာျဖစ္ပါတရ္။
ဒီနည္းလမ္း အတိုင္းပါပဲ။ Zoom Out ေၾကာင့္ ေျပာင္းလဲေပးရမရ္႕ Imag ရဲ႕ Size ကို တြက္ယူလိုက္တာပါ။ 50 ထဲက tbZoomValue.Value ကို ျပန္ႏုတ္ထားတာကေတာ့ ကနဦးတည္းက မူရင္း Image Size ကို 50 မွာ Zero Line ခ်ခဲ့လို႔ပါ။ ဒီပံုစံအတိုင္း က်ေနာ္ 5% ေလွ်ာ့ခ်တဲ့ ZoomOut တစ္ခုကို တြက္ျပပါ့မရ္။ ဥပမာ - က်ေနာ္တို႔ Image Size က 1024x768 ရွိတရ္ဆိုပါစို႔။ သူ႔ကိုမွ 5% ZoomOut လုပ္မရ္ေပါ့။ ဒီေတာ့ ပံုေသနည္းထဲကို ျဖတ္ၾကည့္ပါမရ္။
reWidth = cloneImg.Width - ((cloneImg.Width * (50 - tbZoomValue.Value)) / 100); reWidth = 1024 – ((1024 * (50 - 45))/100); reWidth = 1024 – ((1024 * 5)/100); reWidth = 1024 – (5120/100); reWidth = 1024 – 51; reWidth = 973;ဒါဆို Width = 1024 ကို 5% ZoomOut လုပ္တဲ့အခါမွာ ေျပာင္းလဲသြားတဲ့ reWidth = 973 ကို ရရွိပါၿပီ။ က်ေနာ္တို႔ Height ကို ဆက္တြက္ၾကည့္မရ္။
reHeight = cloneImg.Height - ((cloneImg.Height * (50 - tbZoomValue.Value)) / 100); reHeight = 768 – ((768 * (50 - 45))/100); reHeight = 768 – ((768 * 5)/100); reHeight = 768 – (3840/100); reHeight = 768 – 38; reHeight = 730;ဒါဆို Height = 768 ကို 5% ZoomOut လုပ္တဲ့အခါမွာ ေျပာင္းလဲသြားတဲ့ reHeight = 730 ကို ရရွိပါၿပီ။ ဒီေတာ့ 1024x768 ရွိေသာ Image တစ္ခုကို 5% ZoomOut လုပ္ရင္ 973x730 ရရွိမွာပါ။ ဒီနည္းအတိုင္း ရာခိုင္ႏႈန္း(%) သို႔မဟုတ္ TrackBar Value အႏုတ္ဘက္သို႔ ေျပာင္းလဲမူအေပၚ မူတည္ၿပီး ZoomOut Processing အတြက္ Width and Height ေျပာင္းလဲသြားမွာပဲ ျဖစ္ပါတရ္။ ေနာက္တစ္ဆင့္မွာေတာ့ ZoomOut ျဖစ္သြားေသာ Width and Height အတိုင္း Image ကုိ သိုေလွာင္ဖို႔ Bitmap Container တစ္ခု ဖန္တီးလိုက္ပါတရ္။ ၿပီးရင္ေတာ့ ၄င္း Bitmap အတိုင္း Grahic ဆြဲယူပါ့မရ္လို႔ ခိုင္းပါတရ္။ Graphic ဆြဲၿပီးသြားရင္ေတာ့ က်ေနာ္တို႔ ZoomOut Image တစ္ခုရပါၿပီး ဒီေကာင့္ကို မူရင္း Image Viewer ျဖစ္တဲ့ PictureBox ေပၚသို႔ ျပန္ဆြဲတင္ေပးလိုက္ယံုပါပဲဗ်ာ။ PictureBox ရဲ႕ Size ကို Rebuilt လုပ္ထားတာကေတာ့ ေျပာင္းလဲသြားေသာ ZoomOut Image အတိုင္း PictureBox Size ကုိ fixed ျဖစ္ေနေအာင္ပဲျဖစ္ပါတရ္။
ZoomIn အတြက္ တြက္ခ်က္မႈကလည္း ZoomOut ရဲ႕ သေဘာတရားအတိုင္းပါပဲဗ်ာ။ က်ေနာ္အေသးစိတ္ မရွင္းေတာ့ပါဘူး။ ((cloneImg.Width * (tbZoomValue.Value - 50)) / 100) ဒါက Percentage တြက္ယူတဲ့အပိုင္းပါ။ TrackBar Value က 50(Zero Line Value) ထက္ႀကီးသြားမွာျဖစ္လို႔ ျပန္ႏုတ္ေပးျခင္းျဖင့္ ZoomIn လုပ္ေပးမရ္႕ Percentage တန္ဖိုးကို တြက္ယူထားတာပါ။ မူရင္း Width and Height နဲ႔ ျပန္ေပါင္းေပးထားတာကေတာ့ မူလ Image ထက္ တြက္ထုတ္ထားေသာ Percentage အတိုင္း ႀကီးသြားေစခ်င္လို႔ပါ။ ဒီေလာက္ဆိုရင္ေတာ့ Zoom In/Out ကို Percentage နဲ႔ လုပ္ႏိုင္တဲ့ နည္းလမ္းေလးကို နားလည္ႏိုင္ၾကၿပိလို႔ ထင္ပါတရ္။
ပိုၿပီးနားလည္သြားေအာင္ Coding အျပည့္အစံုကို ေအာက္မွာ ေလ့လာၾကည့္လိုက္ၾကပါအံုးဗ်ာ။
Result ကိုေတာ့ ပံုမွာ ၾကည့္ရင္ အရွင္းႀကီး သိႏိုင္ပါလိမ့္မရ္။ မိတ္ေဆြ၊ ညီအစ္ကို၊ ေမာင္ႏွမအားလံုး ေလ့လာျခင္းျဖင့္ ေက်နပ္ႏိုင္ၾကပါေစ။



