java特粗宋体_JavaCV/javacpp opencv 结合freetype显示汉字

opencv 写中文到图片上 网上有很多都是本地安装的 然后配合freetype工作  javacv使用的是javacpp  不能用c/c++的直接解决方案, 翻看了opencv的各个modules  发现在opencv_contrib的modules下有freetype这个模块

下载源码

然后 vim opencv/cppbuild.sh  找到 找到并打开freetype模块的编译

BUILD_CONTRIB_X=".... -DBUILD_opencv_dnn_modern=OFF -DBUILD_opencv_freetype=ON-DBUILD_opencv_dpm=OFF -DBUILD_opencv_face=ON -DBUILD_opencv_hfs=OFF -DBUILD_opencv_latentsvm=OFF ....."

可能mvn仓库中没有SNAPSHOT的 javacpp  可以将源码一并clone下来 然后手工编译

cd javacpp

mvn install -DskipTests

mvn install -DskipTests -pl .,opencv

然后会下载opencv的 c++版本库

等下载解压完  用等mvn 编译完(需要很长时间)  下载玩完就可以先停掉 (机器好的可以忽略哈) 实际可能并没有编译freetype模块

下面有些细节

修改上面的cppbuild.sh 后  mvn构建会将freetype和harfbuzz加入构建

78103f3f14c3ad70f35bcc6fbb3a51e9.png

依赖 freetype harfbuzz  可以先 brew install freetype harfbuzz(maxos) 确保 freetype在 待构建的列表中(如果本地没有安装freetype harfbuzz 很可能出现在 Unavaliable的列表里)

07e9e43bcf6621c0876cdbcb639e1e8a.png

然后再下面的构建中可以看到

6921d4e594ded4d2caf46e3b54708971.png

然而按照上面编译完成 还是没法用freetype 因为没有添加java的接口

添加如下的映射类

javacpp-presets/opencv/src/main/java/org/bytedeco/javacpp/presets/opencv_freetype.java

package org.bytedeco.javacpp.presets;

import org.bytedeco.javacpp.annotation.Platform;

import org.bytedeco.javacpp.annotation.Properties;

import org.bytedeco.javacpp.tools.InfoMap;

import org.bytedeco.javacpp.tools.InfoMapper;

@Properties(

inherit = {opencv_core.class,opencv_imgproc.class},

value = {

@Platform(

include = {""},

link = "opencv_freetype@.3.4"

),

@Platform(value = "ios", preload = "libopencv_freetype"),

@Platform(value = "windows", link = "opencv_freetype342")

},

target = "org.bytedeco.javacpp.opencv_freetype"

)

public class opencv_freetype implements InfoMapper {

@Override public void map(InfoMap infoMap) {

}

后面会自动根据 freetype.cpp 接口文件 生成 javacpp-presets/opencv/src/main/java/org/bytedeco/javacpp/presets/opencv_freetype.java 详细的方法映射文件(一开始我也以为要自己手写  后面按照其他文件的方式随便写了一个可以编译的  mvn package的时候就被自动生成的给覆盖了 应该不用自己写 可以自动生成的)

03cfe97f0014087d727edc04417db783.png

Cpp 文件在javacpp-presets/opencv/cppbuild/macosx-x86_64/opencv_contrib-3.4.2/modules/freetype/include/opencv2/freetype.hpp

这个接口文件可以看下

namespace cv {

namespace freetype {

//! @addtogroup freetype

//! @{

class CV_EXPORTS_W FreeType2 : public Algorithm

{

public:

/** @brief Load font data.

The function loadFontData loads font data.

@param fontFileName FontFile Name

@param id face_index to select a font faces in a single file.

*/

CV_WRAP virtual void loadFontData(String fontFileName, int id) = 0;

/** @brief Set Split Number from Bezier-curve to line

The function setSplitNumber set the number of split points from bezier-curve to line.

If you want to draw large glyph, large is better.

If you want to draw small glyph, small is better.

@param num number of split points from bezier-curve to line

*/

CV_WRAP virtual void setSplitNumber( int num ) = 0;

/** @brief Draws a text string. 核心的就是这个可以写UTF编码的 默认opencv_imgproc.putText只能写ascii码

The function putText renders the specified text string in the image. Symbols that cannot be rendered using the specified font are replaced by "Tofu" or non-drawn.

@param img Image.

@param text Text string to be drawn.

@param org Bottom-left/Top-left corner of the text string in the image.

@param fontHeight Drawing font size by pixel unit.

@param color Text color.

@param thickness Thickness of the lines used to draw a text when negative, the glyph is filled. Otherwise, the glyph is drawn with this thickness.

@param line_type Line type. See the line for details.

@param bottomLeftOrigin When true, the image data origin is at the bottom-left corner. Otherwise, it is at the top-left corner.

*/

CV_WRAP virtual void putText(

InputOutputArray img, const String& text, Point org,

int fontHeight, Scalar color,

int thickness, int line_type, bool bottomLeftOrigin

) = 0;

/** @brief Calculates the width and height of a text string.

The function getTextSize calculates and returns the approximate size of a box that contains the specified text.

That is, the following code renders some text, the tight box surrounding it, and the baseline: :

@code

String text = "Funny text inside the box";

int fontHeight = 60;

int thickness = -1;

int linestyle = 8;

Mat img(600, 800, CV_8UC3, Scalar::all(0));

int baseline=0;

cv::Ptr<:freetype::freetype2> ft2;

ft2 = cv::freetype::createFreeType2();

ft2->loadFontData( "./mplus-1p-regular.ttf", 0 );

Size textSize = ft2->getTextSize(text,

fontHeight,

thickness,

&baseline);

if(thickness > 0){

baseline += thickness;

}

// center the text

Point textOrg((img.cols - textSize.width) / 2,

(img.rows + textSize.height) / 2);

// draw the box

rectangle(img, textOrg + Point(0, baseline),

textOrg + Point(textSize.width, -textSize.height),

Scalar(0,255,0),1,8);

// ... and the baseline first

line(img, textOrg + Point(0, thickness),

textOrg + Point(textSize.width, thickness),

Scalar(0, 0, 255),1,8);

// then put the text itself

ft2->putText(img, text, textOrg, fontHeight,

Scalar::all(255), thickness, linestyle, true );

@endcode

@param text Input text string.

@param fontHeight Drawing font size by pixel unit.

@param thickness Thickness of lines used to render the text. See putText for details.

@param[out] baseLine y-coordinate of the baseline relative to the bottom-most text

point.

@return The size of a box that contains the specified text.

@see cv::putText

*/

CV_WRAP virtual Size getTextSize(const String& text,

int fontHeight, int thickness,

CV_OUT int* baseLine) = 0;

};

/** @brief Create FreeType2 Instance

The function createFreeType2 create instance to draw UTF-8 strings.

*/

CV_EXPORTS_W Ptr createFreeType2();

//! @}

} } // namespace freetype

#endif

#endif

生成的java文件是这样的  javacpp-presets/opencv/src/main/java/org/bytedeco/javacpp/opencv_freetype.java

// Targeted by JavaCPP version 1.4.3-SNAPSHOT: DO NOT EDIT THIS FILE

package org.bytedeco.javacpp;

import java.nio.*;

import org.bytedeco.javacpp.*;

import org.bytedeco.javacpp.annotation.*;

import static org.bytedeco.javacpp.opencv_core.*;

import static org.bytedeco.javacpp.opencv_imgproc.*;

public class opencv_freetype extends org.bytedeco.javacpp.presets.opencv_freetype {

static { Loader.load(); }

// Parsed from

//################################################################################

//

// Created by Kumataro

//

//################################################################################

// #ifndef _OPENCV_FREETYPE_H_

// #define _OPENCV_FREETYPE_H_

// #ifdef __cplusplus

// #include

/**

\defgroup freetype Drawing UTF-8 strings with freetype/harfbuzz

This modules is to draw UTF-8 strings with freetype/harfbuzz.

1. Install freetype2 and harfbuzz in your system.

2. Create FreeType2 instance with createFreeType2() function.

3. Load font file with loadFontData() function.

4. Draw text with putText() function.

- If thickness parameter is negative, drawing glyph is filled.

- If thickness parameter is positive, drawing glyph is outlined with thickness.

- If line_type parameter is 16(or CV_AA), drawing glyph is smooth.

*/

/** \addtogroup freetype

* \{ */

@Namespace("cv::freetype") public static class FreeType2 extends Algorithm {

static { Loader.load(); }

/** Pointer cast constructor. Invokes {@link Pointer#Pointer(Pointer)}. */

public FreeType2(Pointer p) { super(p); }

/** \brief Load font data.

The function loadFontData loads font data.

@param fontFileName FontFile Name

@param id face_index to select a font faces in a single file.

*/

public native void loadFontData(@Str BytePointer fontFileName, int id);

public native void loadFontData(@Str String fontFileName, int id);

/** \brief Set Split Number from Bezier-curve to line

The function setSplitNumber set the number of split points from bezier-curve to line.

If you want to draw large glyph, large is better.

If you want to draw small glyph, small is better.

@param num number of split points from bezier-curve to line

*/

public native void setSplitNumber( int num );

/** \brief Draws a text string.

The function putText renders the specified text string in the image. Symbols that cannot be rendered using the specified font are replaced by "Tofu" or non-drawn.

@param img Image.

@param text Text string to be drawn.

@param org Bottom-left/Top-left corner of the text string in the image.

@param fontHeight Drawing font size by pixel unit.

@param color Text color.

@param thickness Thickness of the lines used to draw a text when negative, the glyph is filled. Otherwise, the glyph is drawn with this thickness.

@param line_type Line type. See the line for details.

@param bottomLeftOrigin When true, the image data origin is at the bottom-left corner. Otherwise, it is at the top-left corner.

*/

public native void putText(

@ByVal Mat img, @Str BytePointer text, @ByVal Point org,

int fontHeight, @ByVal Scalar color,

int thickness, int line_type, @Cast("bool") boolean bottomLeftOrigin

);

public native void putText(

@ByVal Mat img, @Str String text, @ByVal Point org,

int fontHeight, @ByVal Scalar color,

int thickness, int line_type, @Cast("bool") boolean bottomLeftOrigin

);

public native void putText(

@ByVal UMat img, @Str String text, @ByVal Point org,

int fontHeight, @ByVal Scalar color,

int thickness, int line_type, @Cast("bool") boolean bottomLeftOrigin

);

public native void putText(

@ByVal UMat img, @Str BytePointer text, @ByVal Point org,

int fontHeight, @ByVal Scalar color,

int thickness, int line_type, @Cast("bool") boolean bottomLeftOrigin

);

public native void putText(

@ByVal GpuMat img, @Str BytePointer text, @ByVal Point org,

int fontHeight, @ByVal Scalar color,

int thickness, int line_type, @Cast("bool") boolean bottomLeftOrigin

);

public native void putText(

@ByVal GpuMat img, @Str String text, @ByVal Point org,

int fontHeight, @ByVal Scalar color,

int thickness, int line_type, @Cast("bool") boolean bottomLeftOrigin

);

/** \brief Calculates the width and height of a text string.

The function getTextSize calculates and returns the approximate size of a box that contains the specified text.

That is, the following code renders some text, the tight box surrounding it, and the baseline: :

{@code

String text = "Funny text inside the box";

int fontHeight = 60;

int thickness = -1;

int linestyle = 8;

Mat img(600, 800, CV_8UC3, Scalar::all(0));

int baseline=0;

cv::Ptr<:freetype::freetype2> ft2;

ft2 = cv::freetype::createFreeType2();

ft2->loadFontData( "./mplus-1p-regular.ttf", 0 );

Size textSize = ft2->getTextSize(text,

fontHeight,

thickness,

&baseline);

if(thickness > 0){

baseline += thickness;

}

// center the text

Point textOrg((img.cols - textSize.width) / 2,

(img.rows + textSize.height) / 2);

// draw the box

rectangle(img, textOrg + Point(0, baseline),

textOrg + Point(textSize.width, -textSize.height),

Scalar(0,255,0),1,8);

// ... and the baseline first

line(img, textOrg + Point(0, thickness),

textOrg + Point(textSize.width, thickness),

Scalar(0, 0, 255),1,8);

// then put the text itself

ft2->putText(img, text, textOrg, fontHeight,

Scalar::all(255), thickness, linestyle, true );

}

@param text Input text string.

@param fontHeight Drawing font size by pixel unit.

@param thickness Thickness of lines used to render the text. See putText for details.

@param [out] baseLine y-coordinate of the baseline relative to the bottom-most text

point.

@return The size of a box that contains the specified text.

@see cv::putText

*/

public native @ByVal Size getTextSize(@Str BytePointer text,

int fontHeight, int thickness,

IntPointer baseLine);

public native @ByVal Size getTextSize(@Str String text,

int fontHeight, int thickness,

IntBuffer baseLine);

public native @ByVal Size getTextSize(@Str BytePointer text,

int fontHeight, int thickness,

int[] baseLine);

public native @ByVal Size getTextSize(@Str String text,

int fontHeight, int thickness,

IntPointer baseLine);

public native @ByVal Size getTextSize(@Str BytePointer text,

int fontHeight, int thickness,

IntBuffer baseLine);

public native @ByVal Size getTextSize(@Str String text,

int fontHeight, int thickness,

int[] baseLine);

}

/** \brief Create FreeType2 Instance

The function createFreeType2 create instance to draw UTF-8 strings.

*/

@Namespace("cv::freetype") public static native @Ptr FreeType2 createFreeType2();

/** \} */

// namespace freetype

// #endif

// #endif

}

编译完成后可以看到最终的 opencv-3.4.2-1.4.3-SNAPSHOT-macosx-x86_64.jar 文件里面多了一个

/org/bytedeco/javacpp/macosx-x86_64/libopencv_freetype.3.4.dylib

按照下面调用API即可

FreeType2 ft2 = opencv_freetype.createFreeType2();

//需要载入一个一种中午的字体 这里是宋体

ft2.loadFontData("src/main/resources/ttf/Songti.ttc", 0);

ft2.setSplitNumber(1);

ft2.putText(mat, //图片

label, //文字

new Point(100,100), //开始的位置

18, //大小 单位是px

Scalar.BLACK, //颜色

1, //thickness 粗细

opencv_core.LINE_4, //线条类型

false); //bottomLeftOrigin=true


版权声明:本文为weixin_30624767原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。