1. Giới thiệu về công cụ phần mềm
Công cụ phần mềm đánh giá, hiệu chỉnh chất lƣợng ảnh viễn thám quang học đƣợc phát triển nhằm phục vụ công tác thực nghiệm để thực hiện các tính tốn và đƣa ra kết quả đánh giá thông số SNR, MTF đối với ảnh viễn thám quang học VNREDSat-1. Từ các kết quả này, có thể thực hiện hiệu chỉnh để tăng cƣờng chất lƣợng ảnh về mặt bức xạ.
Công cụ phần mềm đƣợc thiết kế để có thể thực hiện việc tính tốn, đánh giá và hiệu chỉnh tự động, với đầu vào là dữ liệu ảnh thích hợp để đánh giá, đầu ra là kết quả đánh giá các thông số chất lƣợng ảnh, cũng nhƣ kết quả hiệu chỉnh ảnh.
2. Mã nguồn một số chức năng chính
2.1 Đánh giá DS
# -*- coding: utf-8 -*-
from flask_restplus import Resource, Namespace from . import ds_validation
from . import cpf_to_ds_json from . import compare_ds
from . import image_ds_correction import os
api = Namespace('dark_signal', description='Kiểm định dòng tối')
@api.route('/validate_dark_signal/images_folders_path=<images_folders_path>', endpoint = 'validate-dark-signal')
@api.doc(params={'images_folders_path': 'Đƣờng dẫn đến thƣ mục chứa dữ liệu ảnh'}) class ValidateDarkSignalResource(Resource):
def get(self,images_folders_path):
if not os.path.exists(images_folders_path) or not os.path.isdir(images_folders_path): return {'Lỗi':"Các tham số truyền vào không đúng"}
result_path = ds_validation.validate_dark_signal(images_folders_path) if result_path is not None:
else:
return {"Lỗi":"Khơng kiểm định đƣợc dịng tối"}
@api.route('/convert_cpf_to_json/cpf_path=<cpf_path>', endpoint = 'convert_cpf_to_json')
@api.doc(params={'cpf_path': 'Đƣờng dẫn đến tập tin CPF'}) class ConvertCPFToJsonResource(Resource):
def get(self,cpf_path):
if not os.path.exists(cpf_path) or not os.path.isfile(cpf_path) or not cpf_path.lower().endswith('.cpf'):
return {'Lỗi':"Các tham số truyền vào không đúng"}
result_path = cpf_to_ds_json.convert(cpf_path) if result_path is not None:
return {"Đƣờng dẫn đến file Json":result_path} else:
return {"Lỗi":"Không chuyển đổi đƣợc tập tin CPF"}
@api.route('/compare_dark_signal/json_path1=<json_path1>&json_path2=<json_path2> ', endpoint = 'compare-dark-signal')
@api.doc(params={'json_path1': 'Đƣờng dẫn đến thập tin dòng tối (.json) thứ nhất', 'json_path2': 'Đƣờng dẫn đến thập tin dòng tối (.json) thứ hai'})
class CompareDarkSignalResource(Resource): def get(self,json_path1,json_path2):
if not os.path.exists(json_path1) or not os.path.isfile(json_path1) or not json_path1.lower().endswith('.json') or not os.path.exists(json_path2) or not os.path.isfile(json_path2) or not json_path2.lower().endswith('.json'): return {'Lỗi':"Các tham số truyền vào không đúng"}
compare_ds.compare(json_path1,json_path2)
2.2 Đánh giá PRNU
# -*- coding: utf-8 -*-
from flask_restplus import Resource, Namespace import os
from . import prnu_validation from . import cpf_to_prnu_json from . import compare_prnu
from . import image_prnu_correction
api = Namespace('prnu', description='Kiểm định độ không đồng đều đáp ứng điểm ảnh') @api.route('/validate_prnu/images_folders_path=<images_folders_path>&dark_signal_js on_path=<dark_signal_json_path>&on_ground_cpf_path=<on_ground_cpf_path>', endpoint = 'validate-prnu')
@api.doc(params={'images_folders_path': 'Đƣờng dẫn đến thƣ mục chứa ảnh', 'dark_signal_json_path': 'Đƣờng dẫn đến tập tin dòng tối (.json)',
'on_ground_cpf_path': 'Đƣờng dẫn đến tập tin CPF của vệ tinh đo trên mặt đất'})
class ValidatePRNUResource(Resource):
def get(self,images_folders_path, dark_signal_json_path, on_ground_cpf_path): if not os.path.exists(images_folders_path) or not os.path.isdir(images_folders_path) or not os.path.exists(dark_signal_json_path) or not os.path.isfile(dark_signal_json_path) or not dark_signal_json_path.lower().endswith('.json') or not
os.path.exists(on_ground_cpf_path) or not os.path.isfile(on_ground_cpf_path) or not on_ground_cpf_path.lower().endswith('.cpf'):
return {'Lỗi':"Các tham số truyền vào không đúng"}
result_path = prnu_validation.validate_prnu(images_folders_path, dark_signal_json_path, on_ground_cpf_path)
if result_path is not None:
else:
return {"Lỗi":"Không đánh giá đƣợc PRNU"}
@api.route('/convert_cpf_to_json/cpf_path=<cpf_path>', endpoint = 'convert-cpf-to- json')
@api.doc(params={'cpf_path': 'Đƣờng dẫn đến tập tin CPF'}) class ConvertCPFToJsonResource(Resource):
def get(self,cpf_path):
if not os.path.exists(cpf_path) or not os.path.isfile(cpf_path) or not cpf_path.lower().endswith('.cpf'):
return {'Lỗi':"Các tham số truyền vào không đúng"}
result_path = cpf_to_prnu_json.convert(cpf_path) if result_path is not None:
return {"Đƣờng dẫn đến tập tin chứa kết quả":result_path} else:
return {"Lỗi":"Không chuyển đổi đƣợc định dạng tập tin CPF"}
@api.route('/compare_prnu/json_path1=<json_path1>&json_path2=<json_path2>', endpoint = 'compare-prnu')
@api.doc(params={'json_path1': 'Đƣờng dẫn đến tập tin PRNU (.json) thứ nhất', 'json_path2': 'Đƣờng dẫn đến tập tin PRNU (.json) thứ hai'})
class ComparePRNUResource(Resource): def get(self,json_path1,json_path2):
if not os.path.exists(json_path1) or not os.path.isfile(json_path1) or not json_path1.lower().endswith('.json') or not os.path.exists(json_path2) or not os.path.isfile(json_path2) or not json_path2.lower().endswith('.json'):
return {'Lỗi':"Các tham số truyền vào không đúng"}
compare_prnu.compare(json_path1,json_path2)
2.3 Đánh giá SNR
# -*- coding: utf-8 -*-
from flask_restplus import Resource, Namespace from . import snr_validation_async
import os def to_number(s): if s is None: return None try: float(s) try: return int(s) except ValueError: return float(s) except ValueError:
print(s, ' is not a number') return None
api = Namespace('signal_to_noise', description=Đánh giá tỉ lệ tín hiệu trên nhiễu') @api.route('/validate_snr/image_path=<image_path>&rotate=<rotate>', endpoint = 'validate-signal-to-noise-ratio')
@api.doc(params={'image_path': 'Đƣờng dẫn đến tập tin dữ liệu ảnh định dạng TIFF 10bits',
'rotate':'Góc quay ảnh theo chiều ngƣợc kim đồng hồ'}) class ValidateSNRResource(Resource):
def get(self,image_path,rotate):
if not os.path.exists(image_path) or not os.path.isfile(image_path) or not image_path.lower().endswith('.tif') or to_number(rotate) is None:
return {'Lỗi':"Tham số truyền vào không đúng"}
snr_validation_async.validate_snr(image_path,to_number(rotate)) return {"Thông báo":"Lựa chọn vùng kiểm định trên ảnh hiện lên"}
2.4 Đánh giá MTF
def calculate_MTF(self): fig = plt.figure()
fig.suptitle(filename + ' MTF analysis with region (y1, y2, x1, x2) = ' + str(self.roi), fontsize=10)
plt.subplot(2, 3, 1)
plt.imshow(np.array(self.data), cmap='gray') plt.title("Cropped area")
edges = cv2.Canny(self.data, self.min, self.max-5) plt.subplot(2, 3, 2)
plt.imshow(edges, cmap='gray') plt.title("Detected Edge")
row_edge, col_edge = np.where(edges == 255) z = np.polyfit(np.flipud(col_edge), row_edge, 1) angle_radians = np.arctan(z[0]) angle_deg = angle_radians * (180/3.14) if abs(angle_deg) < 45: self.data = np.transpose(self.data) self.compute_esf() # -*- coding: utf-8 -*-
from flask_restplus import Resource, Namespace from . import mtf_validation_async_normalized import os
api = Namespace('modulation_transfer_function', description='Đánh giá định hàm truyền modun')
@api.route('/validate_across_track_mtf/image_path=<image_path>', endpoint = 'validate-modulation-transfer-function-across-track')
@api.doc(params={'image_path': 'Đƣờng dẫn đến tập tin dữ liệu ảnh định dạng TIFF 10bits'})
def get(self,image_path):
if not os.path.exists(image_path) or not os.path.isfile(image_path) or not image_path.lower().endswith('.tif'):
return {'Lỗi':"Tham số truyền vào không đúng"}
mtf_validation_async_normalized.validate_mtf(image_path,along_track=False) return {"Thông báo":"Chọn vùng chuyển đổi từ trắng - đen hoặc đen - trắng theo chiều ngang trên ảnh"}
@api.route('/validate_along_track_mtf/image_path=<image_path>', endpoint = 'validate- modulation-transfer-function-along-track')
@api.doc(params={'image_path': 'Đƣờng dẫn đến tập tin dữ liệu ảnh định dạng TIFF 10bits'})
class ValidateModulationTransferFunctionAlongTrackResource(Resource): def get(self,image_path):
if not os.path.exists(image_path) or not os.path.isfile(image_path) or not image_path.lower().endswith('.tif'):
return {'Lỗi':"Tham số truyền vào không đúng"}
mtf_validation_async_normalized.validate_mtf(image_path,along_track=True) return {"Thông báo":"Chọn vùng chuyển đổi từ trắng - đen hoặc đen - trắng theo chiều dọc trên ảnh"}