├── Demo ├── fmnet.cnn ├── read2.pyc ├── __pycache__ │ └── read2.cpython-35.pyc ├── Plot_Kagan_angle │ ├── sub_conpa.m │ ├── Plot_predicted_probability.m │ ├── Plot_kagan.m │ └── sub_kang.m ├── README ├── predict.py ├── read2.py └── train.py ├── README.md ├── LICENSE └── .gitignore /Demo/fmnet.cnn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congcy/FMNet/HEAD/Demo/fmnet.cnn -------------------------------------------------------------------------------- /Demo/read2.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congcy/FMNet/HEAD/Demo/read2.pyc -------------------------------------------------------------------------------- /Demo/__pycache__/read2.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congcy/FMNet/HEAD/Demo/__pycache__/read2.cpython-35.pyc -------------------------------------------------------------------------------- /Demo/Plot_Kagan_angle/sub_conpa.m: -------------------------------------------------------------------------------- 1 | function [pa_con]=conpa(pa_flag,pa_beg,pa_end,pa_np) 2 | pa_con=pa_flag*(pa_end-pa_beg)/pa_np+pa_beg; 3 | end -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FMNet 2 | FMNet: Earthquake Focal Mechanism Estimation by using a Fully Convolutional Neural Network 3 | -------------------------------------------------------------------------------------------- 4 | Please download data from the supplementary files of this publication: 5 | "Kuang, W., Yuan, C., & Zhang, J. (2021). Real-time determination of earthquake focal mechanism via deep learning. Nature communications, 12(1), 1-8." 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Congcong Yuan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Demo/Plot_Kagan_angle/Plot_predicted_probability.m: -------------------------------------------------------------------------------- 1 | % 2 | clear; 3 | clc; 4 | close all; 5 | 6 | count=0; 7 | numev=972; 8 | for i=1:200:numev 9 | filename_test=sprintf('../test_output/predict_%06d.mat',i); 10 | load(filename_test); 11 | 12 | count_fig=0; 13 | figure; 14 | for k=1:3 15 | amp_true=true(:,:,k); 16 | amp_pred=pred(:,:,k); 17 | count_fig=count_fig+1; 18 | subplot(3,1,count_fig); 19 | plot(amp_true,'linewidth',2,'color','k'); 20 | hold on; 21 | plot(amp_pred,'linewidth',2,'color','r'); 22 | xlim([0 length(amp_true)]); 23 | ylim([0 1]); 24 | set(gca,'xticklabel',[]); 25 | switch k 26 | case 1 27 | xlabel('strike'); 28 | case 2 29 | xlabel('dip'); 30 | case 3 31 | xlabel('rake'); 32 | end 33 | ylabel('Probability'); 34 | legend('true','predicted'); 35 | end 36 | set(gcf,'unit','centimeters','position',[5 2 18 12]); 37 | end 38 | 39 | 40 | -------------------------------------------------------------------------------- /Demo/README: -------------------------------------------------------------------------------- 1 | 2 | This file contains descriptions and steps for retraining/using our FMNet model. 3 | Authorized by Wenhuan Kuang 4 | Date: Nov 23, 2020 5 | If having any questions or suggestions, please email to: kuangwh@ustc.edu.cn 6 | 7 | General description: 8 | We have provided several files as follows: 9 | The FMNet model architecture --> train.py 10 | The FMNet well-trained model --> fmnet.cnn 11 | The FMNet prediction code --> predict.py 12 | A small test dataset --> test_data 13 | 14 | Additionally, we also provide: 15 | Our test output results --> test_out_ours 16 | Kagan angle calculation code --> Plot_Kagan_angle 17 | 18 | 1, System requirements: 19 | It is trained and tested on Linux system, 20 | Linux version 4.4.0-31-generic (buildd@lgw01-16) 21 | (gcc version 5.3.1 20160413 (Ubuntu 5.3.1-14ubuntu2.1) ) 22 | 23 | Python is required. The version we used: Python 3.5.2 24 | 25 | 2, No need to installation 26 | 27 | 3, We have provided a demo of testing dataset, 28 | To run the prediction demo, type in "python predict.py" 29 | Expected output are predicted probability stored under "test_output" 30 | Output files are saved in matlab format, each file represents one test sample 31 | We have provided our predicted outputs under "test_output_ours" for your comparison 32 | 33 | 4, To plot the Kagan angle histogram using Matlab, go to folder "Plot_Kagan_angle" 34 | (1) Plot_kagan.m is for plotting the Kagan angle distribution histogram 35 | (2) Plot_predicted_probability.m is for plotting the predicted probability. 36 | (3) sub_kang.m is a subroutine from Matlab open source library for calculating Kagan angle 37 | (4) sub_conpa.m is a subroutine for converting the output to strike,dip,and rake 38 | 39 | You can set the data path to our results '../test_output_ours/predict_%06d.mat' to compare. 40 | -------------------------------------------------------------------------------- /Demo/Plot_Kagan_angle/Plot_kagan.m: -------------------------------------------------------------------------------- 1 | % 2 | clear; 3 | clc; 4 | close all; 5 | 6 | np_out=[128,128,128]; 7 | 8 | strike_beg=0; 9 | strike_end=360; 10 | dip_beg=0; 11 | dip_end=90; 12 | rake_beg=-90; 13 | rake_end=90; 14 | 15 | numev=972; 16 | for i=1:numev 17 | filename_test=sprintf('../test_output/predict_%06d.mat',i); 18 | load(filename_test); 19 | 20 | % get the index of maximum values 21 | true_flag_strike=find(true(:,:,1)==max(true(:,:,1))); 22 | true_flag_dip=find(true(:,:,2)==max(true(:,:,2))); 23 | true_flag_rake=find(true(:,:,3)==max(true(:,:,3))); 24 | pred_flag_strike=find(pred(:,:,1)==max(pred(:,:,1))); 25 | pred_flag_dip=find(pred(:,:,2)==max(pred(:,:,2))); 26 | pred_flag_rake=find(pred(:,:,3)==max(pred(:,:,3))); 27 | 28 | % convert index to strike, dip, and rake 29 | true_strike=sub_conpa(true_flag_strike,strike_beg,strike_end,np_out(1)); 30 | true_dip=sub_conpa(true_flag_dip,dip_beg,dip_end,np_out(2)); 31 | true_rake=sub_conpa(true_flag_rake,rake_beg,rake_end,np_out(3)); 32 | pred_strike=sub_conpa(pred_flag_strike,strike_beg,strike_end,np_out(1)); 33 | pred_dip=sub_conpa(pred_flag_dip,dip_beg,dip_end,np_out(2)); 34 | pred_rake=sub_conpa(pred_flag_rake,rake_beg,rake_end,np_out(3)); 35 | 36 | % calculate the Kagan angle (subroutine is from by matlab open source library) 37 | [rotangle,theta,phi]=sub_kang([true_strike,true_dip,true_rake],[pred_strike,pred_dip,pred_rake]); 38 | kang(i)=rotangle; 39 | end 40 | 41 | % calculate percentage (kagan angle <= 20 degree) 42 | kang=real(kang); 43 | num1_kang=find(kang<=20); 44 | num2_kang=find(kang>20); 45 | fprintf('Good is %f, bad is %f\n',length(num1_kang)/numev,length(num2_kang)/numev); 46 | 47 | %% plot the histogram of Kagan angles 48 | figure; 49 | histogram(kang,100); 50 | axis([-0.5 121 0 450]); 51 | xlabel('Kagan angles','fontweight','bold'); 52 | ylabel('Counts','fontweight','bold'); 53 | set(findobj('FontSize',10),'FontSize',14,'fontweight','bold'); 54 | set(gcf,'unit','centimeters','position',[5 2 22 14]); 55 | 56 | -------------------------------------------------------------------------------- /Demo/predict.py: -------------------------------------------------------------------------------- 1 | ''' 2 | FMNet prediction: 3 | This code uses the well-trained network model named "fmnet.cnn". 4 | It will perform the prediction for the three angles of a focal mechanism. 5 | A small test dataset is provided. You can directly run the model on the small test dataset. 6 | ''' 7 | 8 | from __future__ import print_function 9 | import os 10 | #os.environ["CUDA_VISIBLE_DEVICES"] = "6,7" 11 | import keras 12 | from keras.datasets import mnist 13 | from keras import losses 14 | from keras import optimizers 15 | from keras.models import Sequential 16 | from keras.models import Sequential,load_model, Model 17 | from keras.layers import Input, Dense, Dropout, Flatten 18 | from keras.layers import Conv1D,Conv2D,MaxPooling1D,MaxPooling2D,BatchNormalization 19 | from keras.layers import UpSampling1D,UpSampling2D,MaxPooling1D,MaxPooling2D 20 | from keras.layers import Cropping1D,Cropping2D,ZeroPadding1D,ZeroPadding2D 21 | from keras.layers.advanced_activations import LeakyReLU 22 | from keras import backend as K 23 | from keras.utils import plot_model 24 | import scipy.stats as stats 25 | import read2 26 | import scipy.io as sio 27 | import numpy as np 28 | import time 29 | import sys 30 | import math 31 | np.random.seed(7) 32 | 33 | test_step=1; 34 | 35 | xm,xn,x_test,ym,yn,y_test=read2.load_data(sgynam='test_data',sgyf1=1,sgyt1=1,step1=test_step,sgyf2=1,sgyt2=1,step2=1) 36 | 37 | print(x_test.shape) 38 | print(y_test.shape) 39 | 40 | # input image dimensions 41 | img_rows, img_cols = xm, xn 42 | out_rows, out_cols = ym, yn 43 | 44 | # the data, shuffled and split between train and test sets 45 | x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1) 46 | y_test = y_test.reshape(y_test.shape[0], 1, out_rows, out_cols) 47 | 48 | 49 | x_test = x_test.astype('float32') 50 | y_test = y_test.astype('float32') 51 | 52 | print('x_test shape:', x_test.shape) 53 | print('y_test shape:', y_test.shape) 54 | 55 | model = load_model('fmnet.cnn') 56 | y_pred = model.predict([x_test]) 57 | 58 | print(type(y_test)) 59 | print(type(y_pred)) 60 | print(y_test.shape) 61 | print(y_pred.shape) 62 | 63 | output_folder = "test_output" 64 | if not os.path.exists(output_folder): 65 | os.mkdir(output_folder) 66 | 67 | for i in range(y_pred.shape[0]): 68 | out_test=(y_test[i]) 69 | out_pred=(y_pred[i]) 70 | filename="test_output/predict_%06d.mat" %(i+1) 71 | sio.savemat(filename,{'true':out_test,'pred':out_pred}) 72 | -------------------------------------------------------------------------------- /Demo/read2.py: -------------------------------------------------------------------------------- 1 | import struct 2 | import numpy as np 3 | import random 4 | import time #for time.sleep 5 | import math 6 | import scipy.misc #for imresize 7 | import gc #for release mem 8 | import scipy.io as sio 9 | import sys 10 | 11 | 12 | def norm(data): 13 | maxval=np.max(data) 14 | minval=np.min(data) 15 | if abs(maxval-minval) < 0.0001: 16 | print("wrong data\n") 17 | sys.exit(0); 18 | return [(float(i)-minval)/float(maxval-minval) for i in data] 19 | def norm_sgy1(data): 20 | return [[abs(float(i)) for i in j] for j in data] 21 | 22 | def read_sgy(sgynam='test.sgy'): 23 | try: 24 | binsgy = open(sgynam,'r') 25 | except IOError: 26 | return 0; 27 | flag=1; 28 | return flag; 29 | def read_file(filename='test.txt'): 30 | try: 31 | fp = open(filename,'r') 32 | except IOError: 33 | return [] 34 | get=fp.read() 35 | mw = get.splitlines() 36 | fp.close() 37 | return mw; 38 | 39 | def load_data(sgynam='file',sgyf1=0,sgyt1=250,step1=1,sgyf2=0,sgyt2=250,step2=1,shuffle='false'): 40 | data= [] 41 | mag=[] 42 | ydata=[] 43 | for i in range(sgyf1,sgyt1+1,step1): 44 | filename="%s/%06d.mat" %(sgynam,i) 45 | print('filename = %s' %(filename)) 46 | flag = read_sgy(filename); 47 | if flag != 0: 48 | data_mat = sio.loadmat(filename); 49 | data_in=data_mat['amp_3d'] #extract variables we need 50 | for tmp in data_in: 51 | tmp=np.array(tmp) 52 | data.append(tmp) 53 | 54 | mag_in=data_mat['gaus_pa'] #extract variables we need 55 | for tmp in mag_in: 56 | tmp=tmp.transpose() 57 | tmp=np.array(tmp) 58 | mag.append(tmp) 59 | else: 60 | print('large ev_%06d.mat not found' %(i)); 61 | 62 | ydata=mag 63 | index=[i for i in range(len(ydata))] 64 | random.seed(7) 65 | if shuffle == 'true': 66 | random.shuffle(index) 67 | data = [data[i] for i in index] 68 | ydata = [ydata[i] for i in index] 69 | data=np.array(data) 70 | ydata=np.array(ydata) 71 | print("read data finished\n") 72 | return data.shape[1],data.shape[2],data,ydata.shape[1],ydata.shape[2],ydata 73 | 74 | if __name__ == '__main__': 75 | numsgy,len1,data,ydata=load_data() 76 | print (numsgy,len1,len(data),data[1],data.shape,ydata.shape) 77 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | -------------------------------------------------------------------------------- /Demo/Plot_Kagan_angle/sub_kang.m: -------------------------------------------------------------------------------- 1 | function [rotangle,theta,phi]=kagan(mechOld,mechNew) 2 | % 3 | % TO CALCULATE KAGAN angle BETWEEN TWO SOLUTIONS ONLY 4 | % 5 | % usage: 6 | % [rotangle,theta,phi]=kagan([strikeOld,dipOld,rakeOld],[strikeNew,dipNew,rakeNew]) 7 | % all angles are given in [degree] 8 | % 9 | % Provides minimum rotation between two DC mechanisms 10 | % minimum rotation ROTANGLE along axis given by THETA and PHI 11 | % 12 | % After Kagan, Y. Y. (1991). 3-D rotation of double-couple 13 | % earthquake sources, Geophys. J. Int., 106(3), 709-716. 14 | % almost "literary" translated from original Fortran code by P. Kolar 15 | % (kolar@ig.cas.cz) 18/01/2019 16 | % 17 | % cf. eg. : 18 | % http://moho.ess.ucla.edu/~kagan/doc_index.html 19 | % http://peterbird.name/oldFTP/2003107-esupp/ 20 | % 21 | str1old=mechOld(1); 22 | dip1old=mechOld(2); 23 | rake1old=mechOld(3); 24 | str1new=mechNew(1); 25 | dip1new=mechNew(2); 26 | rake1new=mechNew(3); 27 | Q1=quatFps(str1old,dip1old,rake1old); 28 | Q2=quatFps(str1new,dip1new,rake1new); 29 | maxval=180. ; 30 | for i=1:4 31 | Qdum=f4r1(Q1,Q2,i); 32 | rotangle=sphcoor(Qdum); 33 | 34 | if(rotangle < maxval) 35 | maxval=rotangle; 36 | Q=Qdum; 37 | end 38 | 39 | end 40 | [rotangle,theta,phi]=sphcoor(Q); 41 | end 42 | %---------------------------------------------------------- 43 | function QUAT=quatFps(DD,DA,SA) 44 | % calculates rotation quaternion corresponding to given focal mechanism 45 | % 46 | % input: strike (DD), dip (DA), rake (SA) 47 | % output: QUAT 48 | ERR=1.e-15; 49 | IC=1; 50 | ICOD=0; 51 | CDD=cosd(DD); 52 | SDD=sind(DD); 53 | CDA=cosd(DA); 54 | SDA=sind(DA); 55 | CSA=cosd(SA); 56 | SSA=sind(SA); 57 | S1=CSA*SDD-SSA*CDA*CDD; 58 | S2=-CSA*CDD-SSA*CDA*SDD; 59 | S3=-SSA*SDA; 60 | V1=SDA*CDD; 61 | V2=SDA*SDD; 62 | V3=-CDA; 63 | AN1=S2*V3-V2*S3; 64 | AN2=V1*S3-S1*V3; 65 | AN3=S1*V2-V1*S2; 66 | D2=1./sqrt(2.); 67 | T1=(V1+S1)*D2; 68 | T2=(V2+S2)*D2; 69 | T3=(V3+S3)*D2; 70 | P1=(V1-S1)*D2; 71 | P2=(V2-S2)*D2; 72 | P3=(V3-S3)*D2; 73 | U0=( T1+P2+AN3+1.)/4.; 74 | U1=( T1-P2-AN3+1.)/4.; 75 | U2=(-T1+P2-AN3+1.)/4.; 76 | U3=(-T1-P2+AN3+1.)/4.; 77 | UM=max([U0,U1,U2,U3]); 78 | switch UM 79 | case U0 80 | ICOD=1*IC; 81 | U0=sqrt(U0); 82 | U3=(T2-P1)/(4.*U0); 83 | U2=(AN1-T3)/(4.*U0); 84 | U1=(P3-AN2)/(4.*U0); 85 | 86 | case U1 87 | ICOD=2*IC; 88 | U1=sqrt(U1); 89 | U2=(T2+P1)/(4.*U1); 90 | U3=(AN1+T3)/(4.*U1); 91 | U0=(P3-AN2)/(4*U1); 92 | 93 | case U2 94 | ICOD=3*IC; 95 | U2=sqrt(U2); 96 | U1=(T2+P1)/(4.*U2); 97 | U0=(AN1-T3)/(4.*U2); 98 | U3=(P3+AN2)/(4.*U2); 99 | 100 | case U3 101 | ICOD=4*IC; 102 | U3=sqrt(U3); 103 | U0=(T2-P1)/(4.*U3); 104 | U1=(AN1+T3)/(4.*U3); 105 | U2=(P3+AN2)/(4.*U3); 106 | 107 | otherwise 108 | error(['INTERNAL ERROR 1 -',num2str(ICOD)]); 109 | end 110 | TEMP=U0*U0+U1*U1+U2*U2+U3*U3; 111 | if abs(TEMP-1.) > ERR 112 | error('INTERNAL ERROR 2'); 113 | end 114 | QUAT(1)=U1; 115 | QUAT(2)=U2; 116 | QUAT(3)=U3; 117 | QUAT(4)=U0; 118 | end 119 | %---------------------------------------------------------- 120 | function [ ANGL, THETA, PHI]=sphcoor(QUAT) 121 | % 122 | % returns rotation angle (ANGL) of a counterclockwise rotation 123 | % and spherical coordinates (colatitude THETA and azimuth PHI) of the 124 | % rotation pole. THETA=0 corresponds to vector pointing down. 125 | if QUAT(4)<0., QUAT=-QUAT; end 126 | Q4N=sqrt(1.d0-QUAT(4)^2); 127 | COSTH=1.; 128 | if abs(Q4N) > 1.e-10, COSTH=QUAT(3)/Q4N; end 129 | if abs(COSTH)>1., COSTH=0; end % COSTH=IDINT(COSTH) 130 | THETA=acosd(COSTH); 131 | ANGL=2.*acosd(QUAT(4)); 132 | PHI=0.; 133 | if abs(QUAT(1))>1.e-10 || abs(QUAT(2))>1.e-10 134 | PHI=atan2d(QUAT(2),QUAT(1)); 135 | end 136 | if PHI<0., PHI=PHI+360.; end 137 | end 138 | %---------------------------------------------------------- 139 | function Q3=QUATP(Q1,Q2) 140 | % 141 | % calculates quaternion product Q3=Q2*Q1 142 | % 143 | Q3(1)= Q1(4)*Q2(1)+Q1(3)*Q2(2)-Q1(2)*Q2(3)+Q1(1)*Q2(4); 144 | Q3(2)=-Q1(3)*Q2(1)+Q1(4)*Q2(2)+Q1(1)*Q2(3)+Q1(2)*Q2(4); 145 | Q3(3)= Q1(2)*Q2(1)-Q1(1)*Q2(2)+Q1(4)*Q2(3)+Q1(3)*Q2(4); 146 | Q3(4)=-Q1(1)*Q2(1)-Q1(2)*Q2(2)-Q1(3)*Q2(3)+Q1(4)*Q2(4); 147 | end 148 | %---------------------------------------------------------- 149 | function Q3=QUATD(Q1,Q2) 150 | % 151 | % quaternion division Q3=Q2*Q1^-1 152 | % 153 | QC1(1:3)=-Q1(1:3); 154 | QC1(4)=Q1(4); 155 | Q3=QUATP(QC1,Q2); 156 | end 157 | %----------------------------------------------------------- 158 | function [Q2,QM]=BOXTEST(Q1,ICODE) 159 | % 160 | % if ICODE==0 finds minimal rotation quaternion 161 | % 162 | % if ICODE==N finds rotation quaternion Q2=Q1*(i,j,k,1) for N=(1,2,3,4) 163 | % 164 | QUAT=[1, 0, 0; ... 165 | 0, 1, 0; ... 166 | 0, 0, 1; ... 167 | 0, 0, 0]; 168 | if ICODE==0 169 | ICODE=1; 170 | QM=abs(Q1(1)); 171 | 172 | for IXC=2:4 173 | if abs(Q1(IXC)) > QM 174 | QM=abs(Q1(IXC)); 175 | ICODE=IXC; 176 | end % endif 177 | end % endfor 178 | end % endif 179 | if ICODE==4 180 | Q2=Q1; 181 | else 182 | QUATT(:)=QUAT(:,ICODE); 183 | Q2=QUATP(QUATT,Q1); 184 | end 185 | if Q2(4)<0., Q2=-Q2; end 186 | QM=Q2(4); 187 | end 188 | %---------------------------------------------------------- 189 | function Q=f4r1(Q1,Q2,ICODE) 190 | % 191 | % Q=Q2*(Q1*(i,j,k,1))^-1 for N=(1,2,3,4) 192 | % 193 | % if N=0, then it finds it of the minimum 194 | % 195 | QR1=BOXTEST(Q1,ICODE); 196 | Q= QUATD(QR1,Q2); 197 | end 198 | %=====================eof================================== -------------------------------------------------------------------------------- /Demo/train.py: -------------------------------------------------------------------------------- 1 | ''' 2 | FMNet training: 3 | This code shows the network architecture of our FMNet. 4 | Training data is not provided since it is too large. 5 | You need specify your own training data path if you want to retrain the model. 6 | We have provided the well-trained model named "fmnet.cnn". 7 | ''' 8 | 9 | from __future__ import print_function 10 | import os 11 | os.environ["CUDA_VISIBLE_DEVICES"] = "1,2,3,4" 12 | import keras 13 | from keras.datasets import mnist 14 | from keras import losses 15 | from keras import optimizers 16 | from keras.models import Sequential 17 | from keras.models import Model 18 | from keras.layers import Input, Dense, Dropout, Flatten 19 | from keras.layers import Conv1D,Conv2D,MaxPooling1D,MaxPooling2D,BatchNormalization 20 | from keras.layers import UpSampling1D,UpSampling2D,MaxPooling1D,MaxPooling2D 21 | from keras.layers import Cropping1D,Cropping2D,ZeroPadding1D,ZeroPadding2D 22 | from keras.layers.advanced_activations import LeakyReLU 23 | from keras import backend as K 24 | from keras.utils import plot_model 25 | import scipy.stats as stats 26 | import read2 27 | import numpy as np 28 | import time 29 | import sys 30 | import math 31 | np.random.seed(7) 32 | 33 | train_step=1; 34 | test_step=100; 35 | 36 | xm,xn,x_train,ym,yn,y_train=read2.load_data(sgynam='PLEASE INPUT YOUR TRAINING DATA PATH',sgyf1=1,sgyt1=100000,step1=train_step,sgyf2=1,sgyt2=1,step2=1) 37 | xm,xn,x_test,ym,yn,y_test=read2.load_data(sgynam='PLEASE INPUT YOUR TRAINING DATA PATH',sgyf1=1,sgyt1=100000,step1=test_step,sgyf2=1,sgyt2=1,step2=1) 38 | 39 | batch_size = 16 40 | epochs = 50 41 | 42 | # input image dimensions 43 | img_rows, img_cols = xm, xn 44 | out_rows, out_cols = ym, yn 45 | 46 | x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1) 47 | y_train = y_train.reshape(y_train.shape[0], 1, out_rows, out_cols) 48 | x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1) 49 | y_test = y_test.reshape(y_test.shape[0], 1, out_rows, out_cols) 50 | 51 | main_input_shape = (img_rows, img_cols, 1) 52 | 53 | x_train = x_train.astype('float32') 54 | x_test = x_test.astype('float32') 55 | y_train = y_train.astype('float32') 56 | y_test = y_test.astype('float32') 57 | 58 | print('x_train shape:', x_train.shape) 59 | print('y_train shape:', y_train.shape) 60 | print('x_test shape:', x_test.shape) 61 | print('y_test shape:', y_test.shape) 62 | 63 | main_input = Input(shape=main_input_shape,name='main_input') 64 | x=Conv2D(64, kernel_size=(3,3),padding='same')(main_input) 65 | x=MaxPooling2D(pool_size=(2,2),padding='same')(x) # 1 66 | x=LeakyReLU(alpha=0.2)(x) 67 | x=BatchNormalization(axis=-1,momentum=0.99,epsilon=0.001,center=True,scale=True, 68 | beta_initializer='zeros', gamma_initializer='ones', moving_mean_initializer='zeros', 69 | moving_variance_initializer='ones')(x) 70 | x=Conv2D(64, kernel_size=(3,3),padding='same')(x) 71 | x=MaxPooling2D(pool_size=(2,2),padding='same')(x) #2 72 | x=LeakyReLU(alpha=0.2)(x) 73 | x=BatchNormalization(axis=-1,momentum=0.99,epsilon=0.001,center=True,scale=True, 74 | beta_initializer='zeros', gamma_initializer='ones', moving_mean_initializer='zeros', 75 | moving_variance_initializer='ones')(x) 76 | x=Conv2D(64, kernel_size=(3,3),padding='same')(x) 77 | x=MaxPooling2D(pool_size=(2,2),padding='same')(x) #3 78 | x=LeakyReLU(alpha=0.2)(x) 79 | x=BatchNormalization(axis=-1,momentum=0.99,epsilon=0.001,center=True,scale=True, 80 | beta_initializer='zeros', gamma_initializer='ones', moving_mean_initializer='zeros', 81 | moving_variance_initializer='ones')(x) 82 | x=Conv2D(64, kernel_size=(3,3),padding='same')(x) 83 | x=MaxPooling2D(pool_size=(2,2),padding='same')(x) #4 84 | x=LeakyReLU(alpha=0.2)(x) 85 | x=BatchNormalization(axis=-1,momentum=0.99,epsilon=0.001,center=True,scale=True, 86 | beta_initializer='zeros', gamma_initializer='ones', moving_mean_initializer='zeros', 87 | moving_variance_initializer='ones')(x) 88 | x=Conv2D(64, kernel_size=(3,3),padding='same')(x) 89 | x=MaxPooling2D(pool_size=(3,2),padding='same')(x) #5 90 | x=LeakyReLU(alpha=0.2)(x) 91 | x=BatchNormalization(axis=-1,momentum=0.99,epsilon=0.001,center=True,scale=True, 92 | beta_initializer='zeros', gamma_initializer='ones', moving_mean_initializer='zeros', 93 | moving_variance_initializer='ones')(x) 94 | x=Conv2D(128, kernel_size=(1,3),padding='same')(x) 95 | x=MaxPooling2D(pool_size=(1,2),padding='same')(x) #6 96 | x=LeakyReLU(alpha=0.2)(x) 97 | x=BatchNormalization(axis=-1,momentum=0.99,epsilon=0.001,center=True,scale=True, 98 | beta_initializer='zeros', gamma_initializer='ones', moving_mean_initializer='zeros', 99 | moving_variance_initializer='ones')(x) 100 | x=Conv2D(128, kernel_size=(1,3),padding='same')(x) 101 | x_encode=MaxPooling2D(pool_size=(1,2),padding='same')(x) #7 102 | print(x_encode.shape) 103 | x=LeakyReLU(alpha=0.2)(x_encode) 104 | x=BatchNormalization(axis=-1,momentum=0.99,epsilon=0.001,center=True,scale=True, 105 | beta_initializer='zeros', gamma_initializer='ones', moving_mean_initializer='zeros', 106 | moving_variance_initializer='ones')(x) 107 | x=Conv2D(128, kernel_size=(1,1),padding='same')(x) 108 | x=UpSampling2D(size=(1,2))(x) #1 109 | x=LeakyReLU(alpha=0.2)(x) 110 | x=BatchNormalization(axis=-1,momentum=0.99,epsilon=0.001,center=True,scale=True, 111 | beta_initializer='zeros', gamma_initializer='ones', moving_mean_initializer='zeros', 112 | moving_variance_initializer='ones')(x) 113 | x=Conv2D(128, kernel_size=(1,3),padding='same')(x) 114 | x=UpSampling2D(size=(1,2))(x) #2 115 | x=LeakyReLU(alpha=0.2)(x) 116 | x=BatchNormalization(axis=-1,momentum=0.99,epsilon=0.001,center=True,scale=True, 117 | beta_initializer='zeros', gamma_initializer='ones', moving_mean_initializer='zeros', 118 | moving_variance_initializer='ones')(x) 119 | x=Conv2D(64, kernel_size=(1,3),padding='same')(x) 120 | x=UpSampling2D(size=(1,2))(x) #3 121 | x=LeakyReLU(alpha=0.2)(x) 122 | x=BatchNormalization(axis=-1,momentum=0.99,epsilon=0.001,center=True,scale=True, 123 | beta_initializer='zeros', gamma_initializer='ones', moving_mean_initializer='zeros', 124 | moving_variance_initializer='ones')(x) 125 | x=Conv2D(64, kernel_size=(1,3),padding='same')(x) 126 | x=UpSampling2D(size=(1,2))(x) #4 127 | x=LeakyReLU(alpha=0.2)(x) 128 | x=BatchNormalization(axis=-1,momentum=0.99,epsilon=0.001,center=True,scale=True, 129 | beta_initializer='zeros', gamma_initializer='ones', moving_mean_initializer='zeros', 130 | moving_variance_initializer='ones')(x) 131 | x=Conv2D(64, kernel_size=(1,3),padding='same')(x) 132 | x=UpSampling2D(size=(1,2))(x) #5 133 | x=LeakyReLU(alpha=0.2)(x) 134 | x=BatchNormalization(axis=-1,momentum=0.99,epsilon=0.001,center=True,scale=True, 135 | beta_initializer='zeros', gamma_initializer='ones', moving_mean_initializer='zeros', 136 | moving_variance_initializer='ones')(x) 137 | x=Conv2D(32, kernel_size=(1,3),padding='same')(x) 138 | x=UpSampling2D(size=(1,2))(x) #6 139 | x=LeakyReLU(alpha=0.2)(x) 140 | x=BatchNormalization(axis=-1,momentum=0.99,epsilon=0.001,center=True,scale=True, 141 | beta_initializer='zeros', gamma_initializer='ones', moving_mean_initializer='zeros', 142 | moving_variance_initializer='ones')(x) 143 | x=Conv2D(32, kernel_size=(1,3),padding='same')(x) 144 | x=UpSampling2D(size=(1,2))(x) #7 145 | x=LeakyReLU(alpha=0.2)(x) 146 | x=BatchNormalization(axis=-1,momentum=0.99,epsilon=0.001,center=True,scale=True, 147 | beta_initializer='zeros', gamma_initializer='ones', moving_mean_initializer='zeros', 148 | moving_variance_initializer='ones')(x) 149 | x=Conv2D(16, kernel_size=(1,3),padding='same')(x) 150 | x=LeakyReLU(alpha=0.2)(x) 151 | x=BatchNormalization(axis=-1,momentum=0.99,epsilon=0.001,center=True,scale=True, 152 | beta_initializer='zeros', gamma_initializer='ones', moving_mean_initializer='zeros', 153 | moving_variance_initializer='ones')(x) 154 | main_output=Conv2D(3, kernel_size=(1,3),padding='same')(x) 155 | print(main_output.shape) 156 | 157 | model = Model(inputs=[main_input],outputs=[main_output]) 158 | model_encode = Model(inputs=[main_input],outputs=[x_encode]) 159 | optimizer = keras.optimizers.Adam(lr=0.001,beta_1=0.9,beta_2=0.999,epsilon=1e-08) 160 | 161 | model.compile(loss='mse', 162 | optimizer=optimizer, 163 | metrics=['accuracy']) 164 | 165 | history_callback=model.fit([x_train], 166 | [y_train], 167 | batch_size=batch_size, 168 | epochs=epochs, 169 | verbose=1, 170 | validation_data=([x_test], [y_test])) 171 | 172 | # Open the save commond when you retrain the model 173 | #model.save('fmnet.cnn') 174 | #model_encode.save('encode.cnn') 175 | --------------------------------------------------------------------------------