GeoTools柵格數(shù)據(jù)分析之圖像變化檢測

功能需求:給定同一區(qū)域不同時間的無人機影像數(shù)據(jù)搜锰,求出區(qū)域內(nèi)影像變化部分,并矢量化成GeoJSON返回給前端署照。
1.將兩幅圖像進行相減與二值化操作
    public GridCoverage2D tiffSubtract(String sourceTiffPath, String targetTiffPath, float diffLimit)
            throws IOException {
        File sourceTiff = new File(sourceTiffPath);
        File targetTiff = new File(targetTiffPath);

        if (!sourceTiff.exists() || !targetTiff.exists()) {
            throw new FileNotFoundException(sourceTiffPath + " or " + targetTiffPath + " do not exist!");
        }

        // 中間數(shù)據(jù)tiff存儲路徑
        String tempTiff = sourceTiff.getParent() + File.separator + "output.tiff";
        // tiff文件坐標系設置
        Hints tiffHints = new Hints();
        tiffHints.add(new Hints(Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER, Boolean.TRUE));
        tiffHints.add(new Hints(Hints.DEFAULT_COORDINATE_REFERENCE_SYSTEM, DefaultGeographicCRS.WGS84));

        GeoTiffReader sourceReader = new GeoTiffReader(sourceTiff, tiffHints);
        GeoTiffReader targetReader = new GeoTiffReader(targetTiff, tiffHints);

        GridCoverage2D sourceCoverage = sourceReader.read(null);
        GridCoverage2D targetCoverage = targetReader.read(null);
        RenderedImage sourceImage = sourceCoverage.getRenderableImage(0, 1).createDefaultRendering();
        RenderedImage targetImage = targetCoverage.getRenderableImage(0, 1).createDefaultRendering();
        Raster sourceRaster = sourceImage.getData();
        Raster targetRaster = targetImage.getData();

        int width = sourceRaster.getWidth();
        int height = sourceRaster.getHeight();
        // System.out.println("pixels : width:" + width + ";height:" + height);

        Envelope2D sourceEnv = sourceCoverage.getEnvelope2D();

        float[][] difference = new float[height][width];
        float s;
        float t;
        // 修改算法,提取差異值大于閾值的部分
        // 將圖像二值化
        for (int x = 0; x < width - 1; x++) {
            for (int y = 0; y < height - 1; y++) {
//              System.out.println("x:" + x + ";y:" + y);
                s = sourceRaster.getSampleFloat(x, y, 1);
                t = targetRaster.getSampleFloat(x, y, 1);
                float diff = t - s;
                if (diff > diffLimit) {
                    difference[y][x] = 100f;
                } else {
                    difference[y][x] = 0f;
                }
            }
        }

        GridCoverageFactory factory = new GridCoverageFactory();
        GridCoverage2D outputCoverage = factory.create("subtractTiff", difference, sourceEnv);
        GeoTiffWriter writer = new GeoTiffWriter(new File(tempTiff));
        writer.write(outputCoverage, null);
        writer.dispose();
        return outputCoverage;
    }
2.調(diào)用geoTools的PolygonExtractionProcess將圖像相減操作結果進行矢量化
    public String polygonExtraction(GridCoverage2D tiffCoverage, String shpPath)
            throws MismatchedDimensionException, IndexOutOfBoundsException, NoSuchAuthorityCodeException,
            ParseException, FactoryException, TransformException, SchemaException, IOException {
        PolygonExtractionProcess process = new PolygonExtractionProcess();
        SimpleFeatureCollection features = process.execute(tiffCoverage, 0, Boolean.TRUE, null, null, null, null);

        features = this.polygonPostprocess(features, 10d);

        SimpleFeatureType type = features.getSchema();

//      ShapeFileWriter.INSTANCE.write(shpPath, features, type);
        this.toGeoJSON(features);

        return shpPath;
    }
3.對矢量化后的多邊形對象進行過濾喇勋,刪除面積過小的細碎多邊形
private SimpleFeatureCollection polygonPostprocess(SimpleFeatureCollection features, double aeraLimit)
            throws IndexOutOfBoundsException, ParseException, NoSuchAuthorityCodeException, FactoryException,
            MismatchedDimensionException, TransformException, SchemaException {
        //坐標轉換,從4326轉成3857
        CoordinateReferenceSystem dataCRS = DefaultGeographicCRS.WGS84;
        CoordinateReferenceSystem targerCRS = CRS.decode("EPSG:3857");
        boolean lenient = true; // allow for some error due to different datums
        MathTransform transform = CRS.findMathTransform(dataCRS, targerCRS, lenient);

        final SimpleFeatureType TYPE = DataUtilities.createType("Location",
                "the_geom:Polygon:srid=3857,DN:String,Aera:Double");

        List<SimpleFeature> projectedFeatureList = new ArrayList<SimpleFeature>();

        GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();
        WKTReader reader = new WKTReader(geometryFactory);
        SimpleFeatureBuilder builder = new SimpleFeatureBuilder(TYPE);

        SimpleFeatureIterator iterator = features.features();
        try {
            while (iterator.hasNext()) {
                SimpleFeature feature = iterator.next();
                Polygon polygon = (Polygon) feature.getDefaultGeometry();
                polygon = (Polygon) JTS.transform(polygon, transform);
                double aera = polygon.getArea();
                // 多邊形面積大于閾值
                if (aera >= aeraLimit) {
                    builder.add(polygon);
                    builder.add(feature.getAttribute(1).toString());
                    builder.add(aera);
                    SimpleFeature tempFeature = builder.buildFeature(null);
                    projectedFeatureList.add(tempFeature);
                }
            }
        } finally {
            iterator.close();
        }

        System.out.println(projectedFeatureList.size());
        return new ListFeatureCollection(TYPE, projectedFeatureList);
    }
4.將最終結果以GeoJSON格式返回
    private void toGeoJSON(SimpleFeatureCollection featureCollection) {
        SimpleFeatureIterator it = featureCollection.features();
        GeoJsonWriter geoJsonWriter = new GeoJsonWriter();
        
        while(it.hasNext()) {
            SimpleFeature tempFeature = it.next();
            
            Geometry geometry = (Geometry) tempFeature.getDefaultGeometry();
            
            String json = geoJsonWriter.write(geometry);
            
            System.out.println(json);
        }
    }
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末娶眷,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子枉层,更是在濱河造成了極大的恐慌泉褐,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件返干,死亡現(xiàn)場離奇詭異兴枯,居然都是意外死亡,警方通過查閱死者的電腦和手機矩欠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門财剖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人癌淮,你說我怎么就攤上這事躺坟。” “怎么了乳蓄?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵咪橙,是天一觀的道長。 經(jīng)常有香客問我虚倒,道長美侦,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任魂奥,我火速辦了婚禮菠剩,結果婚禮上,老公的妹妹穿的比我還像新娘耻煤。我一直安慰自己具壮,他們只是感情好准颓,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著棺妓,像睡著了一般攘已。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上怜跑,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天样勃,我揣著相機與錄音,去河邊找鬼妆艘。 笑死彤灶,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的批旺。 我是一名探鬼主播幌陕,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼汽煮!你這毒婦竟也來了搏熄?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤暇赤,失蹤者是張志新(化名)和其女友劉穎心例,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鞋囊,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡止后,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了溜腐。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片译株。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖挺益,靈堂內(nèi)的尸體忽然破棺而出歉糜,到底是詐尸還是另有隱情,我是刑警寧澤望众,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布匪补,位于F島的核電站,受9級特大地震影響烂翰,放射性物質發(fā)生泄漏夯缺。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一甘耿、第九天 我趴在偏房一處隱蔽的房頂上張望踊兜。 院中可真熱鬧,春花似錦棵里、人聲如沸润文。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽典蝌。三九已至,卻和暖如春头谜,著一層夾襖步出監(jiān)牢的瞬間骏掀,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工柱告, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留截驮,地道東北人。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓际度,卻偏偏與公主長得像葵袭,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子乖菱,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 因為要做一個地圖操作的項目坡锡,需要用到這個地圖庫,但是查詢官方API麻煩窒所,而且這個地圖框架的API做的用起來確實太麻...
    虛幻的銹色閱讀 33,902評論 1 15
  • 圖像處理(ImageMagick) 介紹安裝/配置要求安裝運行時配置資源類型預定義常數(shù)例子基本用法Imagick ...
    daos閱讀 2,363評論 0 1
  • 如何制作透明背景的圖片鹉勒? 首先,只有GIF才可以使用透明吵取,所以在保存文件的時候不要選擇保存或另存為禽额,而是直接選“輸...
    蘇州暮雨閱讀 2,720評論 0 15
  • 111. [動畫系統(tǒng)]如何將其他類型的動畫轉換成關鍵幀動畫? 動畫->點緩存->關鍵幀 112. [動畫]Unit...
    胤醚貔貅閱讀 13,022評論 3 90
  • 到了這個年紀皮官,也許父母可以沒心沒肺脯倒,但我不能,我不能在二十歲的年紀把四十歲還該聯(lián)系的人得罪臣疑,讓別人覺得我處...
    Mx夢兮閱讀 233評論 0 0