មេរៀនទី២៖ JavaScript សម្រាប់ Earth Engine¶
ព័ត៌មានមេរៀន
រយៈពេលបង្រៀនដែលស្នើ៖ ៣ ម៉ោង · មេរៀនទី ២ ក្នុងចំណោម ១៥
និស្សិតភូមិវិទ្យាជាច្រើនបារម្ភថា ពួកគេត្រូវក្លាយជាអ្នកសរសេរកម្មវិធីមុនប្រើ Earth Engine។ តាមពិត ស្គ្រីបភាគច្រើនក្នុងវគ្គនេះប្រើតែ ធាតុ JavaScript ប្រហែលដប់ និង លំនាំតែមួយ៖ ត្រង → អនុវត្ត → សង្ខេប។ អ្វីដែលពិបាកពិតប្រាកដ មិនមែនវាក្យសម្ពន្ធទេ ប៉ុន្តែជាការយល់ថា កូដរបស់អ្នកដំណើរការនៅកន្លែងពីរផ្សេងគ្នា៖ ក្នុងកម្មវិធីរុករក និងនៅលើម៉ាស៊ីនមេរបស់ Google។
មេរៀននេះបង្រៀន JavaScript គ្រប់គ្រាន់សម្រាប់ Earth Engine ពន្យល់ភាពខុសគ្នារវាង client និង server និងណែនាំមុខងារសំខាន់បំផុត map()។
២.១. គោលបំណងសិក្សា¶
បន្ទាប់ពីបញ្ចប់មេរៀន និស្សិតអាច៖
- ប្រើអថេរ អារេ វត្ថុ (object) និងមុខងារ (function) ក្នុង JavaScript។
- បែងចែកវត្ថុ JavaScript ធម្មតា ពីវត្ថុ Earth Engine (
ee.*) ហើយពន្យល់ថាហេតុអ្វីវាប្រព្រឹត្តខុសគ្នា។ - ស្គាល់ប្រភេទវត្ថុ Earth Engine សំខាន់ៗ៖ Image ImageCollection Geometry Feature FeatureCollection និង Reducer។
- សរសេរកូដដោយភ្ជាប់មុខងារ (method chaining) និងប្រើ
map()ជំនួសforloop។ - អានសារកំហុសក្នុង Console ហើយកែកំហុសទូទៅ។
ចំណេះដឹងមុនត្រូវមាន¶
- មេរៀនទី១៖ Code Editor និងស្គ្រីបដំបូង។
- សៀវភៅទី២៖ ស្រទាប់វ៉ិចទ័រ និងតារាងគុណលក្ខណៈ (ដើម្បីយល់ Feature)។
២.២. ស្ថានភាពបើកមេរៀន៖ កូដដែលមើលទៅត្រឹមត្រូវ ប៉ុន្តែមិនដំណើរការ¶
និស្សិតម្នាក់ចង់បោះពុម្ពចំនួនរូបភាពលើខេត្តរបស់គាត់ ហើយបើចំនួនលើស ៥០ គាត់ចង់ឃើញពាក្យ «គ្រប់គ្រាន់»។ គាត់សរសេរ៖
កូដនេះដំណើរការដោយគ្មានកំហុស ប៉ុន្តែវាបោះពុម្ព «មិនគ្រប់» ជានិច្ច ទោះបីមានរូបភាព ២៩០ ក៏ដោយ។ ហេតុអ្វី? ព្រោះ n មិនមែនជាលេខ ២៩០ នៅក្នុងកម្មវិធីរុករកទេ៖ វាជា ការណែនាំ ឱ្យម៉ាស៊ីនមេរាប់ ហើយ JavaScript ធម្មតាមិនដឹងពីតម្លៃរបស់វានៅពេលប្រៀបធៀប។
សំណួរដែលមេរៀននេះឆ្លើយ៖
- តើកូដ Earth Engine ដំណើរការនៅឯណា និងនៅពេលណា?
- តើត្រូវសរសេរលក្ខខណ្ឌ និង loop យ៉ាងដូចម្ដេច នៅពេលទិន្នន័យនៅលើម៉ាស៊ីនមេ?
២.៣. ទ្រឹស្ដីស្នូល¶
២.៣.១. JavaScript គ្រប់គ្រាន់សម្រាប់ Earth Engine¶
JavaScript ជាភាសាដែលកម្មវិធីរុករកទាំងអស់យល់។ សម្រាប់វគ្គនេះ យើងត្រូវការតែធាតុដូចខាងក្រោម៖
// ១. អថេរ៖ ដាក់ឈ្មោះឱ្យតម្លៃ
var province = 'Kampong Chhnang';
var year = 2024;
// ២. អារេ (list)៖ តម្លៃច្រើនតាមលំដាប់
var bands = ['B4', 'B3', 'B2'];
// ៣. វត្ថុ (object/dictionary)៖ ឈ្មោះ → តម្លៃ
var vis = {bands: bands, min: 0, max: 3000};
// ៤. មុខងារ៖ ការងារដែលប្រើឡើងវិញបាន
function addNDVI(img) {
var ndvi = img.normalizedDifference(['B8', 'B4']).rename('NDVI');
return img.addBands(ndvi);
}
// ៥. មតិយោបល់ (comment)៖ ពន្យល់កូដ មិនដំណើរការ
ច្បាប់តូចៗដែលត្រូវចាំ៖ បញ្ចប់បន្ទាត់ដោយ ; អក្សរត្រូវក្នុងសញ្ញា '...' ឈ្មោះប្រកាន់អក្សរធំតូច (Map ≠ map) ហើយវង់ក្រចក () [] {} ត្រូវបិទជាគូជានិច្ច។ Code Editor គូសក្រហមលើកំហុសវាក្យសម្ព័ន្ធមុនអ្នកចុច Run។
២.៣.២. Client និង Server៖ កូដដំណើរការនៅពីរកន្លែង¶
អានរូបនេះ
- ee.Number(5) មិនមែនលេខ ៥ ក្នុងកម្មវិធីរុករកទេ៖ វាជាការណែនាំឱ្យម៉ាស៊ីនមេគណនា។
- ប្រើ .add() .gt() ee.Algorithms.If() ជំនួស + > និង if។
- print() និង Map.addLayer() ស្នើលទ្ធផលពីម៉ាស៊ីនមេ។
នៅពេលអ្នកសរសេរ var n = s2.size(); កម្មវិធីរុករកមិនបានរាប់អ្វីទាំងអស់ទេ។ វាបង្កើត ការពិពណ៌នា «រាប់ធាតុក្នុង s2» ហើយរក្សាទុកក្នុងអថេរ n។ តម្លៃពិតគណនាតែពេលអ្នកសួរវា តាមរយៈ print(n) Map.addLayer() ឬ Export។ ដូច្នេះ៖
- វត្ថុ JavaScript ធម្មតា (
5'abc'[1,2]) រស់នៅលើ client (កម្មវិធីរុករក)។ - វត្ថុ
ee.*(ee.Numberee.Imageee.List) រស់នៅលើ server ហើយត្រូវប្រើមុខងាររបស់វាផ្ទាល់៖
| ធ្វើលើ client (ខុសសម្រាប់ ee) | ធ្វើលើ server (ត្រូវ) |
|---|---|
n > 50 |
n.gt(50) |
a + b |
a.add(b) |
if (...) {...} |
ee.Algorithms.If(cond, a, b) ឬ filter |
for (...) |
.map(function(x) {...}) |
list[0] |
list.get(0) |
getInfo() ៖ ប្រើតិចបំផុត
n.getInfo() ទាញតម្លៃពីម៉ាស៊ីនមេមកកម្មវិធីរុករក ហើយ បង្កក កម្មវិធីរុករករហូតដល់ទទួលបាន។ វាដំណើរការលើតម្លៃតូច ប៉ុន្តែធ្វើឱ្យស្គ្រីបយឺត ឬគាំងលើទិន្នន័យធំ។ ប្រើ print() ជំនួស ព្រោះវាទាញតម្លៃដោយមិនបង្កក។
២.៣.៣. វត្ថុ Earth Engine សំខាន់ៗ¶
អានរូបនេះ
- រ៉ាស្ទ័រ៖ ee.Image (មួយ) និង ee.ImageCollection (ច្រើន)។
- វ៉ិចទ័រ៖ ee.Geometry → ee.Feature → ee.FeatureCollection (ដូចស្រទាប់ QGIS)។
- Reducer៖ បម្លែងតម្លៃច្រើនទៅជាស្ថិតិ (មេរៀនទី៤)។
| វត្ថុ | ដូចអ្វីក្នុង QGIS | មុខងារប្រើញឹកញាប់ |
|---|---|---|
ee.Image |
ស្រទាប់រ៉ាស្ទ័រ (ក្រុមរលកច្រើន) | select normalizedDifference updateMask clip |
ee.ImageCollection |
ថតដែលមានរ៉ាស្ទ័រច្រើន | filterDate filterBounds map median |
ee.Geometry |
ធរណីមាត្រមួយ | Point Rectangle buffer area |
ee.Feature |
វត្ថុមួយ + គុណលក្ខណៈ | get set geometry |
ee.FeatureCollection |
ស្រទាប់វ៉ិចទ័រ | filter map reduceColumns |
ee.Reducer |
ស្ថិតិ | mean median sum histogram |
ឈ្មោះក្រុមរលក គុណលក្ខណៈ (properties) និងប្រព័ន្ធកូអរដោនេ ត្រូវបានរក្សាទុកជាមួយវត្ថុនីមួយៗ។ print(img) បង្ហាញព័ត៌មានទាំងនេះក្នុង Console៖ ទម្លាប់ល្អគឺ print វត្ថុរាល់ពេលអ្នកមិនប្រាកដ។
២.៣.៤. ការភ្ជាប់មុខងារ និងការគណនាពន្យារពេល¶
អានរូបនេះ
- មុខងារនីមួយៗមិនប្ដូរវត្ថុដើមទេ៖ វាត្រឡប់វត្ថុថ្មី។
- ត្រងឱ្យបានច្រើនមុន (filterBounds filterDate) ទើបការគណនាលឿន។
- ចុងក្រោយ reducer (median) បម្លែងបណ្ដុំទៅជារូបភាពមួយ។
មុខងារ Earth Engine នីមួយៗ ត្រឡប់វត្ថុថ្មី ដោយមិនកែវត្ថុដើមទេ។ ដូច្នេះយើងអាចភ្ជាប់វាជាខ្សែ ហើយអានពីលើចុះក្រោម ដូចជាប្រយោគ៖ «យកបណ្ណសារ → ត្រងតាមខេត្ត → ត្រងតាមឆ្នាំ → ត្រងពពក → យកតម្លៃកណ្ដាល»។
អានរូបនេះ
- បន្ទាត់ var គ្រាន់តែបង្កើតផែនការ (graph) នៃការគណនា។
- ការគណនាពិតកើតឡើងពេល print Map.addLayer ឬ Export។
- នៅកម្រិត zoom ទាប Earth Engine គណនាលើក្រឡាធំ (pyramid) ដើម្បីលឿន។
ការគណនាទាំងមូល ពន្យារពេល (lazy) រហូតដល់ត្រូវការលទ្ធផល។ អត្ថប្រយោជន៍៖ Earth Engine មើលខ្សែការគណនាទាំងមូល ហើយគណនាតែក្រឡាដែលចាំបាច់ នៅគុណភាពដែលត្រូវនឹងកម្រិត zoom របស់ផែនទី។ នេះជាមូលហេតុដែលផែនទីបង្ហាញលឿន ទោះបីការគណនាប្រើរូបភាពរាប់រយក៏ដោយ។
Scale ប្ដូរតាម zoom
នៅពេលអ្នក zoom ចេញ Earth Engine គណនាលើក្រឡាធំជាង (pyramid)។ ដូច្នេះតម្លៃដែលអ្នកឃើញក្នុង Inspector នៅ zoom ទាប អាចខុសពីតម្លៃនៅក្រឡា ១០ ម។ សម្រាប់ស្ថិតិ ត្រូវកំណត់ scale ដោយផ្ទាល់ (មេរៀនទី៤)។
២.៣.៥. map()៖ អនុវត្តមុខងារលើគ្រប់ធាតុ¶
អានរូបនេះ
- for loop ដំណើរការក្នុងកម្មវិធីរុករក ហើយមិនស្គាល់ទំហំពិតនៃ collection។
- map() ផ្ញើមុខងារទៅម៉ាស៊ីនមេ ដែលអនុវត្តលើធាតុនីមួយៗស្របគ្នា។
- ក្នុង map() មិនអាចប្រើ print() getInfo() ឬ Map.addLayer() បានទេ។
map() យកមុខងារមួយ ហើយអនុវត្តវាលើធាតុនីមួយៗនៃ collection ស្របគ្នា នៅលើម៉ាស៊ីនមេ។ លទ្ធផលជា collection ថ្មី ដែលមានចំនួនធាតុដូចគ្នា៖
function addNDVI(img) {
return img.addBands(img.normalizedDifference(['B8', 'B4']).rename('NDVI'));
}
var s2ndvi = s2.map(addNDVI); // គ្រប់រូបភាពមានក្រុមរលក NDVI
print(s2ndvi.first().bandNames()); // ពិនិត្យ
ច្បាប់បីសម្រាប់មុខងារក្នុង map()៖ (១) ត្រូវ return វត្ថុប្រភេទដដែល (Image → Image) (២) មិនអាចប្រើ print() getInfo() ឬ Map.addLayer() ខាងក្នុង និង (៣) មិនអាចប្រើអថេរ JavaScript ដែលប្ដូរតម្លៃក្នុង loop។
ពិសោធន៍៖ map() លើ ImageCollection
ជ្រើសមុខងារ ហើយចុច «ដំណើរការ»។ សង្កេតថារូបភាពនីមួយៗត្រូវបានប្ដូរ ដាច់ដោយឡែកពីគ្នា ហើយចំនួនរូបភាពមិនប្ដូរ។
២.៣.៦. លំនាំ filter → map → reduce¶
អានរូបនេះ
- filter៖ តំបន់ កាលបរិច្ឆេទ ពពក។
- map៖ លុបពពក គណនាសន្ទស្សន៍ កាត់តាមព្រំ។
- reduce៖ median ពេលវេលា ឬស្ថិតិតាមតំបន់។
ស្គ្រីបភាគច្រើនក្នុងសៀវភៅនេះ ធ្វើតាមលំនាំតែមួយ៖ filter (ជ្រើសតែអ្វីដែលត្រូវការ) → map (គណនាលើធាតុនីមួយៗ) → reduce (សង្ខេបជាលទ្ធផលមួយ)។ ឧទាហរណ៍ NDVI អតិបរមារដូវប្រាំង៖
var ndviMax = s2.filterDate('2024-01-01', '2024-04-30') // filter
.map(addNDVI) // map
.select('NDVI')
.max(); // reduce
Map.addLayer(ndviMax, {min: 0, max: 0.8, palette: ['white', 'green']}, 'NDVI អតិបរមា');
២.៣.៧. កំហុសទូទៅ និងការកែ¶
អានរូបនេះ
- សារកំហុសក្នុង Console ប្រាប់លេខបន្ទាត់ និងមូលហេតុ។
- កំហុសអង្គចងចាំ និងពេលវេលា ជាទូទៅដោះស្រាយដោយ Export ឬ scale ធំជាង។
- ឈ្មោះក្រុមរលកខុស ជាកំហុសញឹកញាប់បំផុតពេលប្ដូរពី Sentinel-2 ទៅ Landsat។
នៅពេលស្គ្រីបមិនដំណើរការ សូមធ្វើតាមលំដាប់៖ (១) អានសារក្រហមក្នុង Console និងលេខបន្ទាត់ (២) print() អថេរមុនបន្ទាត់ដែលខុស ដើម្បីមើលប្រភេទ និងឈ្មោះក្រុមរលក (៣) សាកល្បងលើតំបន់តូច និងរយៈពេលខ្លីជាមុន (៤) ស្វែងរកមុខងារក្នុងផ្ទាំង Docs ដើម្បីពិនិត្យអាគុយម៉ង់។
២.៤. ឧទាហរណ៍ដែលបានដោះស្រាយ៖ កែកូដក្នុងស្ថានភាពបើកមេរៀន¶
ជំហានទី១៖ រកមូលហេតុ¶
s2.size() ត្រឡប់ ee.Number (server)។ n > 50 ប្រៀបធៀបវត្ថុមួយ ជាមួយលេខ ៥០ លើ client ដែលតែងមិនពិត។
ជំហានទី២៖ សរសេរលក្ខខណ្ឌលើ server¶
var n = s2.size();
var msg = ee.Algorithms.If(n.gt(50), 'គ្រប់គ្រាន់', 'មិនគ្រប់');
print('ចំនួន', n, msg);
ជំហានទី៣៖ ជម្រើសល្អជាង¶
ជាញឹកញាប់ យើងមិនត្រូវការ if ទាល់តែសោះ៖ filter ដោះស្រាយលក្ខខណ្ឌលើធាតុនីមួយៗ ហើយ print(n) គ្រប់គ្រាន់សម្រាប់មនុស្សសម្រេចចិត្ត។
ជំហានទី៤៖ សេចក្ដីសន្និដ្ឋាន¶
«ក្នុង Earth Engine ត្រូវគិតថាអថេរ ee ជាការណែនាំ មិនមែនជាតម្លៃ។ ប្រៀបធៀប គណនា និងលក្ខខណ្ឌ ត្រូវប្រើមុខងាររបស់ ee (gt add If filter) ដើម្បីឱ្យម៉ាស៊ីនមេគណនា។»
អ្វីដែលយើងមិនអាចសន្និដ្ឋាន
ការដែលស្គ្រីបដំណើរការដោយគ្មានកំហុស មិនបញ្ជាក់ថាលទ្ធផលត្រឹមត្រូវទេ (ដូចឧទាហរណ៍នេះ)។ ត្រូវ print តម្លៃកណ្ដាលផ្លូវ ហើយពិនិត្យថាវាសមហេតុផល។
២.៥. សកម្មភាពអនុវត្ត¶
- លំហាត់ទី២៖ សរសេរមុខងារ addNDVI ប្រើ map() លើ collection មួយឆ្នាំ ហើយបង្កើត NDVI អតិបរមា និងមធ្យម។ មើល លំហាត់ទី២។
- ក្នុងថ្នាក់៖ «ស្វែងរកកំហុស»៖ គ្រូផ្ដល់ស្គ្រីបប្រាំដែលខុស ហើយក្រុមនីមួយៗកែ។
២.៦. ការយល់ច្រឡំដែលត្រូវប្រុងប្រយ័ត្ន¶
១. «ត្រូវជាអ្នកសរសេរកម្មវិធីទើបប្រើ Earth Engine បាន» ស្គ្រីបភាគច្រើនប្រើធាតុ JavaScript តិចតួច និងលំនាំ filter → map → reduce។
២. «var n = col.size() គឺជាលេខ» វាជា ee.Number នៅលើម៉ាស៊ីនមេ។ ត្រូវប្រើ print() ដើម្បីឃើញតម្លៃ។
៣. «map() គឺ for loop» map() ដំណើរការស្របគ្នា ហើយមុខងារខាងក្នុងមិនអាចប្រើ print ឬប្ដូរអថេរខាងក្រៅបានទេ។
៤. «getInfo() ជាវិធីល្អសម្រាប់មើលតម្លៃ» វាបង្កកកម្មវិធីរុករក។ print() ល្អជាង។
៥. «ស្គ្រីបគ្មានកំហុស = លទ្ធផលត្រូវ» កំហុសតក្កវិជ្ជា (ដូចលក្ខខណ្ឌលើ client) មិនបង្ហាញសារកំហុសទេ។
២.៧. សេចក្ដីសង្ខេបមេរៀន¶
JavaScript សម្រាប់ Earth Engine ត្រូវការតែអថេរ អារេ វត្ថុ និងមុខងារ។ ចំណុចសំខាន់គឺការបែងចែក client (កម្មវិធីរុករក) ពី server (ម៉ាស៊ីនមេ)៖ វត្ថុ ee.* ជាការពិពណ៌នាការគណនា ដែលដំណើរការតែពេលត្រូវការលទ្ធផល ហើយត្រូវប្រើមុខងាររបស់វាផ្ទាល់ ជំនួសប្រតិបត្តិករ JavaScript ធម្មតា។
map() អនុវត្តមុខងារលើគ្រប់ធាតុស្របគ្នា ហើយជាមួយ filter និង reduce វាបង្កើតលំនាំស្គ្រីបដែលប្រើក្នុងសៀវភៅទាំងមូល។
គំនិតស្នូលនៃមេរៀន
ក្នុង Earth Engine អ្នកមិនបញ្ជាកុំព្យូទ័រឱ្យធ្វើម្ដងមួយៗទេ៖ អ្នកពិពណ៌នាលទ្ធផលដែលចង់បាន ហើយម៉ាស៊ីនមេរកវិធីគណនាវា។
២.៨. ពាក្យគន្លឹះខ្មែរ–អង់គ្លេស¶
| ពាក្យខ្មែរ | ពាក្យអង់គ្លេស | អត្ថន័យខ្លី |
|---|---|---|
| អថេរ | Variable | ឈ្មោះដែលរក្សាតម្លៃ |
| មុខងារ | Function | ការងារដែលប្រើឡើងវិញបាន |
| ម៉ាស៊ីនភ្ញៀវ | Client | កម្មវិធីរុករករបស់អ្នក |
| ម៉ាស៊ីនមេ | Server | ម៉ាស៊ីនរបស់ Google ដែលគណនា |
| ការភ្ជាប់មុខងារ | Method chaining | ហៅមុខងារជាខ្សែ |
| ការគណនាពន្យារពេល | Lazy evaluation | គណនាតែពេលត្រូវការ |
| map | map | អនុវត្តមុខងារលើគ្រប់ធាតុ |
| Reducer | Reducer | បម្លែងតម្លៃច្រើនជាស្ថិតិ |
២.៩. សំណួររំលឹក និងវាយតម្លៃ¶
ក. សំណួរយល់ដឹង¶
- រាយធាតុ JavaScript ចំនួនបួន ដែលប្រើញឹកញាប់ក្នុង Earth Engine ព្រមឧទាហរណ៍។
- ហេតុអ្វី
n > 50មិនដំណើរការលើ ee.Number? - ពន្យល់ការគណនាពន្យារពេល និងអត្ថប្រយោជន៍របស់វា។
- រាយច្បាប់បីសម្រាប់មុខងារក្នុង map()។
- ហេតុអ្វី print() ល្អជាង getInfo()?
ខ. សំណួរអនុវត្តគោលគំនិត¶
- សរសេរមុខងារដែលបន្ថែមក្រុមរលក NDWI (B3 និង B8) ទៅរូបភាព Sentinel-2។
- កែកូដ៖
var total = 0; col.map(function(img){ total = total + 1; }); - ប្ដូរ
a + b * 2ទៅជាកូដ ee ដែល a និង b ជា ee.Number។ - ហេតុអ្វីតម្លៃក្នុង Inspector នៅ zoom ៨ ខុសពីនៅ zoom ១៥?
- ពិពណ៌នាជំហាន filter → map → reduce សម្រាប់ «NDVI មធ្យមខែមីនា ២០២៤ លើខេត្តតាកែវ»។
គ. កិច្ចការខ្លី¶
យកស្គ្រីបពីលំហាត់ទី១ ហើយបន្ថែមមតិយោបល់ជាភាសាខ្មែរ លើបន្ទាត់នីមួយៗ ដោយប្រាប់ថាបន្ទាត់នោះដំណើរការលើ client ឬ server។
កំណត់សម្គាល់សម្រាប់គ្រូបង្រៀន¶
ក. ការបែងចែកពេលវេលា ១៨០ នាទី¶
| សកម្មភាព | ពេលវេលា |
|---|---|
| ស្ថានភាពបើកមេរៀន៖ if ដែលមិនដំណើរការ | ១៥ នាទី |
| JavaScript មូលដ្ឋាន (សរសេរតាម) | ៣០ នាទី |
| Client និង Server | ២៥ នាទី |
| វត្ថុ Earth Engine | ២០ នាទី |
| Chaining និង lazy evaluation | ២០ នាទី |
| map() · ពិសោធន៍ | ៣០ នាទី |
| filter → map → reduce និងកំហុសទូទៅ | ២៥ នាទី |
| សង្ខេប និងណែនាំលំហាត់ | ១៥ នាទី |
| សរុប | ១៨០ នាទី / ៣ ម៉ោង |
ខ. ការភ្ជាប់ទៅមេរៀនបន្ទាប់¶
យើងអាចត្រង និងអនុវត្តមុខងារលើ collection ហើយ។ ប៉ុន្តែរូបភាពដែលយើងប្រើនៅមានពពក ហើយយើងនៅមិនទាន់ដឹងពីរបៀបផ្គុំរូបភាពរាប់រយជារូបភាពស្អាតមួយ។
សំណួរនេះនាំទៅ មេរៀនទី៣៖ Image Collection ការត្រង ការលុបពពក និង Composite។