Beispiel #1
0
        /// <summary>
        /// 1枚のイメージからフィルム距離を返す。波長と、各面の真の面間隔と実測した2θが必要
        /// </summary>
        /// <param name="p"></param>
        /// <param name="WaveLength"></param>
        /// <param name="FilmDistance"></param>
        /// <param name="FilmDistanceDev"></param>
        public static void FindFilmDistanceFromWaveLength(List <EllipseParameter> ellipses, double WaveLength, ref double FilmDistance, ref double FilmDistanceDev)
        {
            if (ellipses == null || ellipses.Count < 1)
            {
                return;
            }
            double        tempTotal = 0;
            double        weightTotal = 0;
            double        temp, weight;
            List <double> FD = new List <double>();

            for (int i = 0; i < ellipses.Count; i++)
            {
                for (int j = 0; j < ellipses[i].millimeters.Count; j++)
                {
                    if (!double.IsNaN(ellipses[i].millimeters[j]))
                    {
                        temp         = ellipses[i].millimeters[j] / Math.Tan(2 * Math.Asin(WaveLength / 2.0 / ellipses[i].d));
                        weight       = 1;//Math.Pow(Math.Sin(Math.Atan(p[i].pixel1 * p[i].pixelSize / p[i].filmDistance1)), 2);
                        tempTotal   += temp * weight;
                        weightTotal += weight;
                        FD.Add(temp);
                    }
                }
            }
            if (weightTotal > 0 && !double.IsInfinity(weightTotal))
            {
                FilmDistance    = tempTotal / weightTotal;
                FilmDistanceDev = Statistics.Deviation(FD.ToArray()) / Math.Sqrt(FD.Count);
            }
        }
Beispiel #2
0
        /// <summary>
        ///  楕円の中心群とそれらの半径から、真の中心のオフセット位置(offset)と傾き(tau, phi)とそれらの誤差を返す
        /// </summary>
        /// <param name="EllipseCenter"></param>
        /// <param name="Radius"></param>
        /// <param name="CameraLength"></param>
        /// <param name="offset"></param>
        /// <param name="offsetDev"></param>
        /// <param name="tau"></param>
        /// <param name="tauDev"></param>
        /// <param name="phi"></param>
        /// <param name="phiDev"></param>

        public static void GetTiltAndOffset(PointD[] EllipseCenter, double[] Radius, double CameraLength, ref PointD offset, ref PointD offsetDev,
                                            ref double tau, ref double tauDev, ref double phi, ref double phiDev)
        {
            //任意の二点を選んでoffset, tau, phiを計算する
            List <double> offsetXList = new List <double>();
            List <double> offsetYList = new List <double>();
            List <double> tauList     = new List <double>();
            List <double> phiList     = new List <double>();

            for (int i = 0; i < EllipseCenter.Length; i++)
            {
                for (int j = i + 1; j < EllipseCenter.Length; j++)
                {
                    PointD[] ellipseCenterTemp = new PointD[] { EllipseCenter[i], EllipseCenter[j] };
                    double[] radiusTemp        = new double[] { Radius[i], Radius[j] };
                    PointD   offsetTemp        = offset;
                    double   tauTemp           = tau;
                    double   phiTemp           = phi;

                    GetTiltAndOffset(ellipseCenterTemp, radiusTemp, CameraLength, ref offsetTemp, ref tauTemp, ref phiTemp);

                    offsetXList.Add(offsetTemp.X);
                    offsetYList.Add(offsetTemp.Y);
                    tauList.Add(tauTemp);
                    phiList.Add(phiTemp);
                }
            }
            offsetDev = new PointD(Statistics.Deviation(offsetXList.ToArray()), Statistics.Deviation(offsetYList.ToArray()));
            tauDev    = Statistics.Deviation(tauList.ToArray());

            double phiDev1, phiDev2;

            phiDev1 = Statistics.Deviation(phiList.ToArray());
            for (int i = 0; i < phiList.Count; i++)
            {
                if (phiList[i] < 0)
                {
                    phiList[i] += Math.PI;
                }
            }
            phiDev2 = Statistics.Deviation(phiList.ToArray());

            phiDev = Math.Min(phiDev1, phiDev2);

            //全EllipseCenterを用いて、offset, tau, phiを計算する
            GetTiltAndOffset(EllipseCenter, Radius, CameraLength, ref offset, ref tau, ref phi);
        }
Beispiel #3
0
        /// <summary>
        /// 楕円の方程式から、その楕円群をもっとも真円に近づけるパラメータ(PixX, PixY, Ksi)を求める
        /// </summary>
        /// <param name="ellipse"></param>
        /// <param name="PixX"></param>
        /// <param name="PixY"></param>
        /// <param name="Ksi"></param>
        /// <param name="PixXDev"></param>
        /// <param name="PixYDev"></param>
        /// <param name="KsiDev"></param>
        /// <param name="distortion"></param>
        public static void GetPixelShape(EllipseParameter[] ellipse, ref double PixX, ref double PixY, ref double Ksi, ref double PixXDev, ref double PixYDev, ref double KsiDev, bool distortion)
        {
            for (int i = 0; i < ellipse.Length; i++)
            {
                ellipse[i].SetCoeff();
                //RがRになるように調節する
                ellipse[i].Coeff[0] *= ellipse[i].millimeterCalc * ellipse[i].millimeterCalc / 1000000;
                ellipse[i].Coeff[1] *= ellipse[i].millimeterCalc * ellipse[i].millimeterCalc / 1000000;
                ellipse[i].Coeff[2] *= ellipse[i].millimeterCalc * ellipse[i].millimeterCalc / 1000000;
            }

            //半径Rの円 X^2 + Y^2 = R^2 がアフィン変換 { { A, B} , { 0 , C } } という行列で変換されると
            //楕円   a * X^2 + b * X * Y + c * Y^2  = X^2 / A^2 - X * Y * 2B /A^2/C  + Y^2 * (A^2+B^2) /(A^2 C^2) = R^2 に変換される
            //このとき
            //A =  1 / √(a)
            //B = - b /√(a) /√(4ac-b^2)
            //C = 2√(a) /√(4ac-b^2)

            List <double> tempPixX = new List <double>();
            List <double> tempPixY = new List <double>();
            List <double> tempKsi = new List <double>();
            double        A, B, C;

            for (int i = 0; i < ellipse.Length; i++)
            {
                A = Math.Sqrt(1.0 / ellipse[i].Coeff[0]);
                B = -ellipse[i].Coeff[1] / Math.Sqrt(ellipse[i].Coeff[0] * (4 * ellipse[i].Coeff[0] * ellipse[i].Coeff[2] - ellipse[i].Coeff[1] * ellipse[i].Coeff[1]));
                C = 2 * Math.Sqrt(ellipse[i].Coeff[0] / (4 * ellipse[i].Coeff[0] * ellipse[i].Coeff[2] - ellipse[i].Coeff[1] * ellipse[i].Coeff[1]));
                //{ { A, B} , { 0 , C } } * {x, y} = { { PixX , PixY SinKsi } , { 0 , PixelY } } * {X,Y} // ただし {x,y}は真の円上の座標, {X,Y}はピクセル座標
                //だから newPixX = PixX /A, newPixY = PixY /C, tan(newKsi) = C (tanKsi-B) /A
                tempPixX.Add(PixX / A);
                tempPixY.Add(PixY / C);
                tempKsi.Add(Math.Atan(C / A * (Math.Tan(Ksi) - B)));
            }

            PixX    = tempPixX.Average();
            PixXDev = Statistics.Deviation(tempPixX.ToArray());
            PixY    = tempPixY.Average();
            PixYDev = Statistics.Deviation(tempPixY.ToArray());
            if (distortion)
            {
                Ksi    = tempKsi.Average();
                KsiDev = Statistics.Deviation(tempKsi.ToArray());
            }
        }
Beispiel #4
0
        /// <summary>
        /// 一枚の写真中の複数のピークを同時に渡してその加重平均から波長と誤差を計算する (FindWaveLength2を内部的に呼び出す)
        /// </summary>
        /// <param name="p"></param>
        /// <param name="WaveLength"></param>
        /// <param name="WaveLengthDev"></param>
        public static void FindWaveLengthFromMultiPeaks(List <EllipseParameter> ellipses, ref double WaveLength, ref double WaveLengthDev)
        {
            if (ellipses == null || ellipses.Count < 1)
            {
                return;
            }
            double        tempTotal = 0;
            double        temp, sigma1, sigma2, weight;
            double        weightTotal = 0;
            List <double> WL          = new List <double>();

            for (int i = 0; i < ellipses.Count; i++)
            {
                for (int j = i + 1; j < ellipses.Count; j++)
                {
                    for (int k = 0; k < ellipses[i].millimeters.Count; k++)
                    {
                        if (!double.IsNaN(ellipses[i].millimeters[k]) && !double.IsNaN(ellipses[j].millimeters[k]))
                        {
                            double obs1 = ellipses[i].millimeters[k];
                            double obs2 = ellipses[j].millimeters[k];
                            double d1   = ellipses[i].d;
                            double d2   = ellipses[j].d;

                            temp   = FindParameter.FindWaveLength2(obs1, obs2, d1, d2, WaveLength);
                            sigma1 = (FindParameter.FindWaveLength2(obs1 + 0.1, obs2, d1, d2, WaveLength) - temp);
                            sigma2 = (FindParameter.FindWaveLength2(obs1, obs2 + 0.1, d1, d2, WaveLength) - temp);
                            if (sigma1 != 0 || sigma2 != 0)
                            {
                                weight       = 1 / (sigma1 * sigma1 + sigma2 * sigma2);
                                weightTotal += weight;
                                tempTotal   += weight * temp;
                                WL.Add(temp);
                            }
                        }
                    }
                }
            }
            if (weightTotal > 0 && !double.IsInfinity(weightTotal))
            {
                WaveLength    = tempTotal / weightTotal;
                WaveLengthDev = Statistics.Deviation(WL.ToArray()) / Math.Sqrt(Math.Sqrt(2 * WL.Count));
            }
        }
Beispiel #5
0
        /// <summary>
        /// 一枚の写真中の複数のピークと波長+カメラ長からピクセルサイズを計算する (全パターンからの算出)
        /// </summary>
        /// <param name="p"></param>
        /// <param name="WaveLength"></param>
        /// <param name="WaveLengthDev"></param>
        public static void FindPixelSizeFromMultiPeaks(List <Plane> plane, double CameraLength, double WaveLength, ref double PixelSize, ref double PixelSizeDev)
        {
            if (plane == null)
            {
                return;
            }
            double        tempTotal = 0;
            double        temp, sigma1, sigma2, weight;
            double        weightTotal = 0;
            List <double> CL          = new List <double>();

            for (int i = 0; i < plane.Count; i++)
            {
                for (int j = i + 1; j < plane.Count; j++)
                {
                    if (!double.IsNaN(plane[i].MillimeterObs) && !double.IsNaN(plane[j].MillimeterObs) &&
                        plane[i].IsFittingChecked && plane[j].IsFittingChecked)
                    {
                        double obs1 = plane[i].MillimeterObs;
                        double obs2 = plane[j].MillimeterObs;
                        double d1   = plane[i].d;
                        double d2   = plane[j].d;
                        temp = CameraLength * Math.Tan(2 * Math.Asin(GetSinTheta(obs1, obs2, d1, d2, WaveLength))) / obs1 * PixelSize;

                        sigma1 = CameraLength * Math.Tan(2 * Math.Asin(GetSinTheta(obs1 + 0.1, obs2, d1, d2, WaveLength))) / obs1 * PixelSize - temp;
                        sigma2 = CameraLength * Math.Tan(2 * Math.Asin(GetSinTheta(obs1, obs2 + 0.1, d1, d2, WaveLength))) / obs1 * PixelSize - temp;
                        if (sigma1 != 0 || sigma2 != 0)
                        {
                            weight       = 1 / (sigma1 * sigma1 + sigma2 * sigma2);
                            weightTotal += weight;
                            tempTotal   += weight * temp;
                            CL.Add(temp);
                        }
                    }
                }
            }
            if (weightTotal > 0 && !double.IsInfinity(weightTotal))
            {
                PixelSize    = tempTotal / weightTotal;
                PixelSizeDev = Statistics.Deviation(CL.ToArray()) / Math.Sqrt(Math.Sqrt(2 * CL.Count));
            }
        }
Beispiel #6
0
        /// <summary>
        /// 一枚の写真中の複数のピークを同時に渡してその加重平均から波長と誤差を計算する (FindWaveLength2を内部的に呼び出す)
        /// </summary>
        /// <param name="p"></param>
        /// <param name="WaveLength"></param>
        /// <param name="WaveLengthDev"></param>
        public static void FindWaveLengthFromMultiPeaks(List <Plane> plane, ref double WaveLength, ref double WaveLengthDev)
        {
            if (plane == null)
            {
                return;
            }
            double        tempTotal = 0;
            double        temp, sigma1, sigma2, weight;
            double        weightTotal = 0;
            List <double> WL          = new List <double>();

            for (int i = 0; i < plane.Count; i++)
            {
                for (int j = i + 1; j < plane.Count; j++)
                {
                    if (!double.IsNaN(plane[i].MillimeterObs) && !double.IsNaN(plane[j].MillimeterObs) &&
                        plane[i].IsFittingChecked && plane[j].IsFittingChecked)
                    {
                        double obs1 = plane[i].MillimeterObs;
                        double obs2 = plane[j].MillimeterObs;
                        double d1   = plane[i].d;
                        double d2   = plane[j].d;

                        temp   = FindParameter.FindWaveLength2(obs1, obs2, d1, d2, WaveLength);
                        sigma1 = (FindParameter.FindWaveLength2(obs1 + 0.1, obs2, d1, d2, WaveLength) - temp);
                        sigma2 = (FindParameter.FindWaveLength2(obs1, obs2 + 0.1, d1, d2, WaveLength) - temp);
                        if (sigma1 != 0 || sigma2 != 0)
                        {
                            weight       = 1 / (sigma1 * sigma1 + sigma2 * sigma2);
                            weightTotal += weight;
                            tempTotal   += weight * temp;
                            WL.Add(temp);
                        }
                    }
                }
            }
            if (weightTotal > 0 && !double.IsInfinity(weightTotal))
            {
                WaveLength    = tempTotal / weightTotal;
                WaveLengthDev = Statistics.Deviation(WL.ToArray()) / Math.Sqrt(Math.Sqrt(2 * WL.Count));
            }
        }
Beispiel #7
0
        /// <summary>
        /// 2枚のフィルム距離の異なる画像からフィルム距離を返す。フィルム距離の差(誤差無し)が必要
        /// </summary>
        /// <param name="p"></param>
        /// <param name="FilmDistanceDiscrepancy"></param>
        /// <param name="FilmDistance"></param>
        /// <param name="FilmDistanceDev"></param>
        public static void FindFilmDistanceFromDiscrepancy(List <Plane> plane1, List <Plane> plane2, double Discrepancy, ref double FilmDistance, ref double FilmDistanceDev)
        {
            List <double> FD = new List <double>();
            double        temp, dif1, dif2, weight;
            double        tempTotal   = 0;
            double        weightTotal = 0;

            for (int i = 0; i < plane1.Count; i++)
            {
                for (int j = 0; j < plane2.Count; j++)
                {
                    if (plane1[i].strHKL == plane2[j].strHKL &&
                        !double.IsNaN(plane1[i].MillimeterObs) && !double.IsNaN(plane2[j].MillimeterObs) &&
                        plane1[i].IsFittingChecked && plane2[j].IsFittingChecked)
                    {
                        double m1 = plane1[i].MillimeterObs;
                        double m2 = plane2[j].MillimeterObs;

                        temp         = FindCameraLength(m1, m2, Discrepancy);
                        dif1         = FindCameraLength(m1 + 0.1, m2, Discrepancy) - temp;
                        dif2         = FindCameraLength(m1, m2 + 0.1, Discrepancy) - temp;
                        weight       = 1 / (dif1 * dif1 + dif2 * dif2) * 100;
                        weightTotal += weight;
                        tempTotal   += weight * temp;
                        FD.Add(temp);
                    }
                }
            }
            if (weightTotal > 0 && !double.IsInfinity(weightTotal))
            {
                FilmDistance = tempTotal / weightTotal;
                if (FD.Count > 1)
                {
                    FilmDistanceDev = Statistics.Deviation(FD.ToArray()) / Math.Sqrt(FD.Count - 1);
                }
                else
                {
                    FilmDistanceDev = 0;
                }
            }
        }
Beispiel #8
0
        public static void FindSphericalCorrection(List <EllipseParameter> ellipses, double waveLength, double filmDistance, ref double radiusInverse, ref double radiusInverseDev)
        {
            double        weightTotal = 0;
            double        tempRtotal  = 0;
            List <double> r           = new List <double>();

            for (int i = 0; i < ellipses.Count; i++)
            {
                for (int j = i + 1; j < ellipses.Count; j++)
                {
                    for (int k = 0; k < ellipses[i].millimeters.Count; k++)
                    {
                        if (!double.IsNaN(ellipses[i].millimeters[k]) && !double.IsNaN(ellipses[j].millimeters[k]))
                        {
                            double obs1 = ellipses[i].millimeters[k];
                            double obs2 = ellipses[j].millimeters[k];
                            double d1   = ellipses[i].d;
                            double d2   = ellipses[j].d;

                            double tempR  = FindParameter.FindSphericalCorrection(obs1, obs2, d1, d2, waveLength, filmDistance);
                            double sigma1 = FindParameter.FindSphericalCorrection(obs1, obs2 + 0.01, d1, d2, waveLength, filmDistance) - tempR;
                            if (sigma1 != 0)
                            {
                                weightTotal += 1 / (sigma1 * sigma1);
                                tempRtotal  += tempR / (sigma1 * sigma1);
                                r.Add(tempR);
                            }
                        }
                    }
                }
            }

            if (weightTotal > 0 && !double.IsInfinity(weightTotal))
            {
                radiusInverse   += tempRtotal / weightTotal;
                radiusInverseDev = Statistics.Deviation(r.ToArray()) / Math.Sqrt(Math.Sqrt(2 * r.Count));
            }
        }
Beispiel #9
0
        /// <summary>
        /// 2枚のフィルム距離の異なる画像からフィルム距離を返す。フィルム距離の差(誤差無し)が必要
        /// </summary>
        /// <param name="p"></param>
        /// <param name="FilmDistanceDiscrepancy"></param>
        /// <param name="FilmDistance"></param>
        /// <param name="FilmDistanceDev"></param>
        public static void FindFilmDistanceFromDiscrepancy(List <EllipseParameter> ellipses1, List <EllipseParameter> ellipses2, double Discrepancy, ref double FilmDistance, ref double FilmDistanceDev)
        {
            List <double> FD = new List <double>();
            double        temp, dif1, dif2, weight;
            double        tempTotal   = 0;
            double        weightTotal = 0;

            for (int i = 0; i < ellipses1.Count; i++)
            {
                for (int j = 0; j < ellipses2.Count; j++)
                {
                    for (int k = 0; k < ellipses1[i].millimeters.Count; k++)
                    {
                        if (ellipses1[i].strHKL == ellipses2[j].strHKL &&
                            !double.IsNaN(ellipses1[i].millimeters[k]) && !double.IsNaN(ellipses2[j].millimeters[k]))
                        {
                            double m1 = ellipses1[i].millimeters[k];
                            double m2 = ellipses2[j].millimeters[k];

                            temp         = FindCameraLength(m1, m2, Discrepancy);
                            dif1         = FindCameraLength(m1 + 0.1, m2, Discrepancy) - temp;
                            dif2         = FindCameraLength(m1, m2 + 0.1, Discrepancy) - temp;
                            weight       = 1 / (dif1 * dif1 + dif2 * dif2) * 100;
                            weightTotal += weight;
                            tempTotal   += weight * temp;
                            FD.Add(temp);
                        }
                    }
                }
            }
            if (weightTotal > 0 && !double.IsInfinity(weightTotal))
            {
                FilmDistance    = tempTotal / weightTotal;
                FilmDistanceDev = Statistics.Deviation(FD.ToArray()) / Math.Sqrt(FD.Count);
            }
        }
Beispiel #10
0
        /// <summary>
        /// 固定されたピクセルサイズとフィルム距離から波長をかえす
        /// </summary>
        /// <param name="p"></param>
        /// <param name="PixelSize"></param>
        /// <param name="FilmDistance"></param>
        /// <param name="WaveLength"></param>
        /// <param name="WaveLengthDev"></param>
        public static void FindWaveLengthFromFixedPixelSize(List <EllipseParameter> ellipse, double FilmDistance,
                                                            ref double WaveLength, ref double WaveLengthDev)
        {
            //int n = 0;
            double        tempTotal = 0;
            double        weightTotal = 0;
            double        weight, temp, diff;
            List <double> WL = new List <double>();

            for (int i = 0; i < ellipse.Count; i++)
            {
                temp         = 2 * ellipse[i].d * Math.Sin(Math.Atan(ellipse[i].GetAverageRadius() / FilmDistance) / 2);
                diff         = 2 * ellipse[i].d * Math.Sin(Math.Atan((ellipse[i].GetAverageRadius() + 0.1) / FilmDistance) / 2) - temp;
                weight       = 1 / diff / diff;
                weightTotal += weight;
                tempTotal   += weight * temp;
                WL.Add(temp);
            }
            if (weightTotal > 0 && !double.IsInfinity(weightTotal))
            {
                WaveLength    = tempTotal / weightTotal;
                WaveLengthDev = Statistics.Deviation(WL.ToArray()) / Math.Sqrt(WL.Count);
            }
        }