파이썬으로 가져온 이미지를 필터링하는 모듈을 C 언어로 만들었습니다.
빨리 시도하고 싶은 분은 나의 리포지토리를 이용해 주세요.
htps : // 기주 b. 코 m / 소라 미미 / py 모즈 ゜ 이마 게 ぃ l r
파이썬 용 자체 제작 모듈을 만드는 방법
종속 모듈 설치
첫 번째 시도는
helloworld
이므로 불필요하지만, 나중의 이미지 처리 편에서는 numpy, pillow, matplotlib를 사용하고 있으므로 이러한 모듈이 설치되어 있어야합니다. Ubuntu에서 개발한다고 가정합니다. 파이썬 개발 패키지가 필요합니다.sudo apt install python3-dev python3-matplotlib
함수 정의 구조체 작성
static PyMethodDef myMethods[] = {
{ "helloworld", helloworld, METH_NOARGS, "My helloworld function." },
{ NULL }
};
정의의 내용은 {(함수 이름), (함수에 대한 포인터), (인수 전달 방법), (설명문)}의 순서로 기술합니다.
METH_NOARGS
는 인수가 없는 함수의 경우입니다. 인수를 이용하려면 METH_VARARGS
로 합니다.모듈 정의 구조체 작성
static struct PyModuleDef mymodule = {
PyModuleDef_HEAD_INIT,
"mymodule",
"Python3 C API Module",
-1,
myMethods
};
모듈 이름이나 설명 등을 씁니다.
모듈을 초기화하는 함수 작성
PyMODINIT_FUNC PyInit_mymodule(void)
{
import_array();
return PyModule_Create(&mymodule);
}
import_array()
라는 함수 호출은 필요에 따라 작성됩니다. 이번 테마에서는, 화상 처리로 배열을 취급하기 때문에 이것이 필요합니다. 배열을 사용하지 않으면 필요하지 않습니다. 배열 API를 사용하는 모든 소스 코드에서 import_array()
를 실행해야합니다.함수 본문 작성
static PyObject *helloworld(PyObject *self, PyObject *args)
{
fprintf(stderr, "Hello, world\n");
return Py_None;
}
첫 번째 평가판 함수이므로
helloworld
입니다. 나중에 이미지 처리를 수행하는 코드를 구현할 것입니다.빌드용 스크립트 작성
setup.py
from distutils.core import setup, Extension
setup(name = 'mymodule', version = '1.0.0', ext_modules = [Extension('mymodule', ['mymodule.c'])])
빌드
python3 setup.py build_ext -i
긴 이름의
.so
파일이 성공하면 성공합니다.$ ls *.so
mymodule.cpython-35m-x86_64-linux-gnu.so
호출 (Python 측) 프로그램 작성
main.py
import mymodule
mymodule.helloworld()
실행하다
Python 프로그램과 모듈
.so
파일을 같은 디렉토리에 넣은 상태에서 실행합니다.$ python3 main.py
Hello, world
이미지 처리 필터 만들기
예를 들면, 세피아조의 필터를 걸는 함수로 합니다. 함수 이름이
helloworld
에서 sepia
로 변경되었습니다.파이썬 측의 프로그램은 다음과 같습니다.
main.py
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
import mymodule
im = np.array(Image.open('kamo.jpg'))
im = mymodule.sepia(im)
print(type(im))
print(im.dtype)
print(im.shape)
plt.imshow(im)
plt.show()
다음과 같이 작동합니다.
함수 정의를 다음과 같이 합니다.
{ "sepia", sepia, METH_VARARGS, "Sepia tone image filter" },
C 언어측 소스의 발췌입니다.
mymodule.c
static PyObject *sepia(PyObject *self, PyObject *args)
{
PyArrayObject *srcarray;
if (!PyArg_ParseTuple(args, "O", &srcarray)) {
fprintf(stderr, "invalid argument\n");
return Py_None;
}
최초의 (라고 해도 1개만) 인수는 배열입니다. 객체로 가져옵니다.
입력의 배열은, (높이)×(폭)×(채널)의 3차원 배열이므로, 그렇지 않으면 에러로 합니다. 채널수는 3(RGB)로 한정합니다.
if (srcarray->nd != 3) {
fprintf(stderr, "invalid image\n");
return Py_None;
}
if (srcarray->dimensions[2] != 3) {
fprintf(stderr, "invalid image\n");
return Py_None;
}
이미지의 크기를 가져옵니다.
int h = srcarray->dimensions[0];
int w = srcarray->dimensions[1];
필터 처리 결과의 이미지를 포함하는 배열을 확보합니다.
npy_intp dims[] = { h, w, 3 };
PyObject *image = PyArray_SimpleNew(3, dims, NPY_UBYTE);
if (!image) {
fprintf(stderr, "failed to allocate array\n");
return Py_None;
}
(높이)×(너비)×(채널)의 순서를 틀리지 마십시오.
배열로서 확보한 오브젝트는, 그대로 배열 구조체에의 포인터에 캐스트 할 수 있습니다.
PyArrayObject *dstarray = (PyArrayObject *)image;
필터링합니다.
for (int y = 0; y < h; y++) {
uint8_t const *src = (uint8_t const *)srcarray->data + y * w * 3;
uint8_t *dst = (uint8_t *)dstarray->data + y * w * 3;
for (int x = 0; x < w; x++) {
uint8_t r = src[x * 3 + 0];
uint8_t g = src[x * 3 + 1];
uint8_t b = src[x * 3 + 2];
r = pow(r / 255.0, 0.62) * 205 + 19;
g = pow(g / 255.0, 1.00) * 182 + 17;
b = pow(b / 255.0, 1.16) * 156 + 21;
dst[x * 3 + 0] = r;
dst[x * 3 + 1] = g;
dst[x * 3 + 2] = b;
}
}
개체를 반환 종료합니다.
return image;
}
이상입니다.
오류 처리는 생략되었습니다. 잘못된 이미지 파일을 받았을 때와 같이 함수가
None
처음에도 썼습니다만, 모든 소스 코드는 여기 로 공개하고 있습니다.
Reference
이 문제에 관하여(파이썬으로 가져온 이미지를 필터링하는 모듈을 C 언어로 만들었습니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/soramimi_jp/items/a2368b370e3140def0d1텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)