파이썬으로 가져온 이미지를 필터링하는 모듈을 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.)