/// <summary> /// renders the ssim structure into a texture /// </summary> public void GetStructureTexture(ITexture image1, ITexture image2, ITexture dst, Settings s) { Debug.Assert(image1.HasSameDimensions(image2)); Debug.Assert(image1.HasSameDimensions(dst)); var cache = GetCache(image1); var structTex = cache.GetTexture(); using (var data = new ImagesCorrelationStats(cache)) { foreach (var lm in image1.LayerMipmap.Range) { RenderImagesCorrelation(image1, image2, data, lm); RenderStructure(data, structTex, lm); if (!s.Multiscale) { RenderRedToRgba(structTex, dst, lm); } } if (s.Multiscale) { foreach (var lm in image1.LayerMipmap.Range) { RenderContrastStructureMultiscale(structTex, lm); RenderRedToRgba(structTex, dst, lm); } } } cache.StoreTexture(structTex); }
private void RenderContrast(ImagesCorrelationStats src, ITexture dst, LayerMipmapSlice lm) { contrastShader.Run(new [] { src.Image1.Variance, src.Image2.Variance }, dst, lm, models.SharedModel.Upload); }
private void RenderLuminance(ImagesCorrelationStats src, ITexture dst, LayerMipmapSlice lm) { luminanceShader.Run(new [] { src.Image1.Expected, src.Image2.Expected }, dst, lm, models.SharedModel.Upload); }
private void RenderStructure(ImagesCorrelationStats src, ITexture dst, LayerMipmapSlice lm) { structureShader.Run(new [] { src.Image1.Variance, src.Image2.Variance, src.Correlation }, dst, lm, models.SharedModel.Upload); }
private void RenderImagesCorrelation(ITexture src1, ITexture src2, ImagesCorrelationStats dst, LayerMipmapSlice lm) { // calc expected value and variance RenderImageVariance(src1, dst.Image1, lm); RenderImageVariance(src2, dst.Image2, lm); // calc correlation coefficient var lumaMult = dst.Cache.GetTexture(); multiplyShader.Run(new [] { dst.Image1.Luma, dst.Image2.Luma }, lumaMult, lm, models.SharedModel.Upload); // blur result var lumaBlur = dst.Cache.GetTexture(); gaussShader.Run(lumaMult, lumaBlur, lm, models.SharedModel.Upload, dst.Cache); // calc correlation with blurred(luma1*luma2) - mu1*mu2 subtractProductShader.Run(new [] { lumaBlur, dst.Image1.Expected, dst.Image2.Expected }, dst.Correlation, lm, models.SharedModel.Upload); dst.Cache.StoreTexture(lumaMult); dst.Cache.StoreTexture(lumaBlur); }
private void RenderSSIM(ImagesCorrelationStats src, ITexture dst, LayerMipmapSlice lm) { ssimShader2.Run(new [] { src.Image1.Expected, src.Image2.Expected, src.Image1.Variance, src.Image2.Variance, src.Correlation }, dst, lm, models.SharedModel.Upload); }
public Stats GetStats(ITexture image1, ITexture image2, LayerMipmapRange lmRange, Settings s) { Debug.Assert(image1.HasSameDimensions(image2)); Debug.Assert(lmRange.IsSingleMipmap); var cache = GetCache(image1); var lumTex = cache.GetTexture(); var contTex = cache.GetTexture(); var strucTex = cache.GetTexture(); var ssimTex = cache.GetTexture(); using (var data = new ImagesCorrelationStats(cache)) { if (!s.Multiscale) { foreach (var lm in image1.LayerMipmap.RangeOf(lmRange)) { // determine expected value, variance, correlation RenderImagesCorrelation(image1, image2, data, lm); // calc the three components RenderLuminance(data, lumTex, lm); RenderContrast(data, contTex, lm); RenderStructure(data, strucTex, lm); // build ssim //RenderSSIM(data, ssimTex, lm); RenderSSIM(lumTex, strucTex, contTex, ssimTex, lm); } } else // multiscale { int endMipmap = Math.Min(lmRange.Mipmap + 5, image1.NumMipmaps); for (int curMip = lmRange.Mipmap; curMip < endMipmap; ++curMip) { foreach (var lm in image1.LayerMipmap.RangeOf(new LayerMipmapRange(lmRange.Layer, curMip))) { // determine expected value, variance, correlation RenderImagesCorrelation(image1, image2, data, lm); // calc components if (curMip == endMipmap - 1) // luminance only for last mipmap { RenderLuminance(data, lumTex, lm); } RenderContrast(data, contTex, lm); RenderStructure(data, strucTex, lm); } } // combine values of different scales to compute ssim foreach (var lm in image1.LayerMipmap.RangeOf(lmRange)) { // determine appropriate scale scores RenderLuminanceMultiscale(lumTex, lm); RenderContrastStructureMultiscale(contTex, lm); RenderContrastStructureMultiscale(strucTex, lm); // build ssim RenderSSIM(lumTex, strucTex, contTex, ssimTex, lm); } } } var stats = new Stats { Luminance = GetAveragedValue(lumTex, lmRange, s.ExcludeBorders), Contrast = GetAveragedValue(contTex, lmRange, s.ExcludeBorders), Structure = GetAveragedValue(strucTex, lmRange, s.ExcludeBorders), SSIM = GetAveragedValue(ssimTex, lmRange, s.ExcludeBorders) }; cache.StoreTexture(lumTex); cache.StoreTexture(contTex); cache.StoreTexture(strucTex); cache.StoreTexture(ssimTex); return(stats); }