From dd0818db8624713d00801ce4f264f0b96ae145f6 Mon Sep 17 00:00:00 2001 From: build Date: Wed, 5 Feb 2020 16:41:16 +0100 Subject: [PATCH] Add existing files --- makefile | 29 ++ src/ImageRecToolLinux.vcxproj | 92 +++++ src/cmdTcpipClient.c | 130 +++++++ src/cmdTcpipClient.d | 1 + src/cmdTcpipClient.h | 4 + src/cmdTcpipClient.o | Bin 0 -> 3760 bytes src/imageRec.c | 515 +++++++++++++++++++++++++ src/imageRec.d | 3 + src/imageRec.h | 43 +++ src/imageRec.o | Bin 0 -> 15428 bytes src/main.c | 681 ++++++++++++++++++++++++++++++++++ src/main.d | 5 + src/main.o | Bin 0 -> 23284 bytes src/openwrt.config | 14 + 14 files changed, 1517 insertions(+) create mode 100755 makefile create mode 100644 src/ImageRecToolLinux.vcxproj create mode 100644 src/cmdTcpipClient.c create mode 100644 src/cmdTcpipClient.d create mode 100644 src/cmdTcpipClient.h create mode 100644 src/cmdTcpipClient.o create mode 100755 src/imageRec.c create mode 100644 src/imageRec.d create mode 100755 src/imageRec.h create mode 100644 src/imageRec.o create mode 100755 src/main.c create mode 100644 src/main.d create mode 100644 src/main.o create mode 100755 src/openwrt.config diff --git a/makefile b/makefile new file mode 100755 index 0000000..1570ed9 --- /dev/null +++ b/makefile @@ -0,0 +1,29 @@ +#Ensure that openwrt cross-compile environment variables are set prior to calling make: +# ~/bin/openwrt.config + +CC=mipsel-openwrt-linux-gcc + +CFLAGS= -std=gnu99 + +SOURCES= main.c cmdTcpipClient.c imageRec.c + +TARGET ?= imagerec +SRC_DIRS ?= ./src + +SRCS := $(shell find $(SRC_DIRS) -name *.cpp -or -name *.c -or -name *.s) +OBJS := $(addsuffix .o,$(basename $(SRCS))) +DEPS := $(OBJS:.o=.d) + +INC_DIRS := $(shell find $(SRC_DIRS) -type d) +INC_FLAGS := $(addprefix -I,$(INC_DIRS)) + +CPPFLAGS ?= $(INC_FLAGS) -MMD -MP + +$(TARGET): $(OBJS) + $(CC) $(LDFLAGS) $(OBJS) -o $@ $(LOADLIBES) $(LDLIBS) + +.PHONY: clean +clean: + $(RM) $(TARGET) $(OBJS) $(DEPS) + +-include $(DEPS) diff --git a/src/ImageRecToolLinux.vcxproj b/src/ImageRecToolLinux.vcxproj new file mode 100644 index 0000000..a8abb9c --- /dev/null +++ b/src/ImageRecToolLinux.vcxproj @@ -0,0 +1,92 @@ + + + + + Debug + ARM + + + Release + ARM + + + Debug + ARM64 + + + Release + ARM64 + + + Debug + x86 + + + Release + x86 + + + Debug + x64 + + + Release + x64 + + + + {6ad72ab1-e95b-4f4c-89bd-0a3052980eb8} + Linux + ImageRecToolLinux + 15.0 + Linux + 1.0 + Generic + {D51BCBC9-82E9-4017-911E-C93873C4EA2B} + + + + true + + + false + + + true + + + false + + + true + + + false + + + false + + + true + + + + + + + + .out + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/cmdTcpipClient.c b/src/cmdTcpipClient.c new file mode 100644 index 0000000..1e16446 --- /dev/null +++ b/src/cmdTcpipClient.c @@ -0,0 +1,130 @@ +#include +#include +#include +#ifdef __WIN32__ +#include +#include +#else +#include +#include +#endif + +#ifdef __WIN32__ +#pragma comment(lib, "Ws2_32.lib") +#endif + +int lsock; +int csock = 0; + +int startSocket(void) +{ +#ifdef __WIN32__ + WSADATA wsa; + return WSAStartup(MAKEWORD(2, 0), &wsa); +#else + return 0; +#endif +} + +int setupCmdTcpServer(int port) +{ + + struct sockaddr_in addr; + int rc; + rc = startSocket(); + + if (rc != 0) + { + printf("Fehler: startWinsock, fehler code: %d\n", rc); + return 1; + } + else + { + lsock = socket(AF_INET, SOCK_STREAM, 0); + + memset(&addr, 0, sizeof(addr)); // set to 0 + addr.sin_family = AF_INET; + addr.sin_port = htons((unsigned short)port); // port + addr.sin_addr.s_addr = htonl(INADDR_ANY); + + if ((bind(lsock, (struct sockaddr*)& addr, sizeof(addr))) != 0) + { + printf("socket bind failed...\n"); + return 0; + } + else + { + printf("Socket successfully binded..\n"); + + if (listen(lsock, 5)) + { + printf("listen failed\n"); + return 0; + } + } + } + + return 1; +} + +void closeTcpConnection() +{ + char rbuff[1] = { 0 }; + + printf("close connection\n"); + if (csock) + { + shutdown(csock, SHUT_WR); + while (recv(csock, rbuff, 1, 0) > 0); +#ifdef __WIN32__ + closesocket(csock); +#else + close(csock); +#endif + csock = 0; + } + +} + +void sendTcpData(char* data, int lenght) +{ + if (csock) + if (send(csock, data, (unsigned short)lenght, MSG_NOSIGNAL) < 0) closeTcpConnection(); +} + +int waitForTcpData(char* cmdData, int lenght) +{ + int ret = 0; + + do + { + if (csock == 0) + { + printf("wait for incomming connection\n"); + + csock = accept(lsock, NULL, NULL); + + printf("incomming connection\n"); + } + else + { + ret = recv(csock, cmdData, (unsigned int)lenght, 0); + + if (ret == 0) + { + printf("socket closed\n"); + closeTcpConnection(); + } + else if (ret < 0) + { + printf("socket error\n"); + csock = 0; + return 0; + } + } + + } + while (ret < 1); + + return ret; +} \ No newline at end of file diff --git a/src/cmdTcpipClient.d b/src/cmdTcpipClient.d new file mode 100644 index 0000000..7567044 --- /dev/null +++ b/src/cmdTcpipClient.d @@ -0,0 +1 @@ +src/cmdTcpipClient.o: src/cmdTcpipClient.c diff --git a/src/cmdTcpipClient.h b/src/cmdTcpipClient.h new file mode 100644 index 0000000..9348974 --- /dev/null +++ b/src/cmdTcpipClient.h @@ -0,0 +1,4 @@ +int setupCmdTcpServer(int port); +int waitForTcpData(char* cmdData, int lenght); +void sendTcpData(char* data, int lenght); +void closeTcpConnection(); \ No newline at end of file diff --git a/src/cmdTcpipClient.o b/src/cmdTcpipClient.o new file mode 100644 index 0000000000000000000000000000000000000000..37be9f0e62c2059cf84a2dae5eaa61f5c8d351b8 GIT binary patch literal 3760 zcma)8O>9(E6h8CQQV_79XqAd@F%w2DFM~9+5*80y0S#&m7+7HJ%$wJC;`Ghry*K=< z#Ds-0P0B(Oml%n%AgK#XT!12!gau0$F1ujC!iAb>STq^G@4kDdZ(a~R$(?i0cg{Wc z-1E-4cRqRZ=%Gv|BZe|EAZwDyz($e2L6K2qP?9YIAwiEiH+JUbr={ZWmvTj@iVtt* zATJKcjhzFslB4Ne*o?~0OJ!|0F3U@R;aOxzZY^Ofa=u<1<$Or)K+f(LnJfTSb{WYQ z4oJLtu?(&B6|$1=>Wf1TOu1&_>ag6}IVk;wVhQnB#A6>>_<-)aalK!sbFiG$?|`mo z(LA=d5L@i?;KH!n);_0ud=BWCX;(_b%Uo>J@lxj`bjD{N&XC+c>1#S+PhVN>i+Ny< zkJP*muZ@5=0;mhpJLvByRE^=@olZuBn#=bZ%sEhu>5b{tg z_2%I3jx(IJJ;Oseb9kaXsM=p43@4Yrm$yHgt25 z-G8sgo_*t7Wu5h>*8I|Oh8P)rFmI3hcGMeM6Zwd7>U||3tm@ANu6_L*87&3-(!IR0*OJbw6ynACFiw3bov3&D&=cYa2v} zdy!SG`!#E(Qg3)Q+qSXKu^12AuIq*2OuNxIr;MnFS{n5*@_fAnvfF5e9vu6==SKCW zPn$E9dSuNs1FP=4&H4GdKig~YFR+P8xvasDj?oK(WW+=Q6612UZb2mwI*PelTES}oKbLWkv}`C z0lIQt)fPl4U~I*CUe)tC9Go(msY`6^iLMkk*V`%i{giwnC4ZQbt0{RlC9`O7nag!> z#`9@P|9MJQm#D@V@0S=y@Zekk=lZX;j*R+mG44S>uFv}e6`H6QcfNMqZPi;7jk@PY zwkr*mp1A5)byD0G5_(a)HKDAJdBJHfkXBIlqZwVQGVjg9MCPKVAFAJmu*0O)jzZl! zamQf0iM5^y=h{)NdB&H(b5F+x*ve;6la;8V=Bld>H3NfH(4ehIc(>$H;wQoTP%5Xu z`@yG)ZxK09jsjT#@7pAD5xgJ#GVy0bmdSA|-zUc(fE94sJpiZOBjV5De-&~^{~N*S ze-J$XJZehgC5?}0e3UrWGw1X(NgRcFoH*8>Bo2OxIQ(4F_+^b>(fIeoH;Y^&4!*4A zyIQ^vo_`T>Yy5%6SBY;&y!h^1KM2nC!{GU0#I5m?#;3Jh({iNcvs(TNJdaEM3i%5n z54HX`tzV^#^PnNsxp>j=TpPiehe6`t7I8~tggD|U69*rqjP>J`!S{o6{ZZo3PZ0;7 zBaU-jAP&3Fh=VT>hy54ii0_)#|ETrXwSJj6{M;oDPRgQwEOIo1Lyq;+{cxh zd%osX+q2Z{c^&4>cr70c^q|;&GxF@i?|!fg{fAz(afREJC<^M;cI1T!=>HKzM=5k~ zRR{CIJbpB({>L0CRX4X|a9raKzA010^<2VtzNlrSPtjDu7Xjn%HOy(Bv@^P-T^Ryy z{1&!SM1N?LF3~;ZH!yH-ckSjfBOSruOXXmYrtqwkzy!Sh-sh^T`$*fFbI@)Dm?3laSpf9Mb1TB(cbhplbsR0t!4&Q8eHOd>o`?3Y zPNx}L!58ezUc^l7H6Z6e5mE%Y(-z7uFAFkFOyR*pOMPmeR G?EV29w$q~k literal 0 HcmV?d00001 diff --git a/src/imageRec.c b/src/imageRec.c new file mode 100755 index 0000000..b6b7b5a --- /dev/null +++ b/src/imageRec.c @@ -0,0 +1,515 @@ +#include +#include "imageRec.h" + +const short sobelFilterKernel[3][3] = { { 3, 10, 3 }, { 0, 0, 0 }, { -3, -10, -3 } }; +const imageBuffer gausFilterKernel[5] = { 25, 61, 83, 61, 25 }; + +int imageWidth = 0; +int imageHight = 0; +int imageBufferSize = 0; + +int setImageSize(int width, int hight) +{ + imageWidth = width; + imageHight = hight; + imageBufferSize = width * hight; + + return imageBufferSize; +} + +void normalizeImage(imageBuffer* srcImage, imageBuffer* dstImage) +{ + int min = 0xFFFF; + int max = 0; + unsigned int factor; + + for (int i = 0; i < imageBufferSize; i++) + { + if (srcImage[i] < min) min = srcImage[i]; + if (srcImage[i] > max) max = srcImage[i]; + } + + factor = (1 << 30) / (max - min + 1); + + for (int i = 0; i < imageBufferSize; i++) + { + dstImage[i] = (imageBuffer)((srcImage[i] - min) * factor / (1<<14)); + } +} + +void gausFilter(imageBuffer * image, imageBuffer * helperImage) +{ + int n = sizeof(gausFilterKernel) / sizeof(gausFilterKernel[0]); + int acc; + int acck = 0; + int i = 0; + + for (int y = 0; y < imageHight; y++) + { + for (int x = 0; x < imageWidth; x++) + { + acc = 0; + acck = 0; + + for (int j = 0; j < n; j++) + { + int pos = x + j - n / 2; + + if (pos >= 0 && pos < imageWidth) + { + acc += image[i + j - n / 2] * gausFilterKernel[j]; + acck += gausFilterKernel[j]; + } + } + + helperImage[i] = (unsigned short)(acc / acck); + + i++; + } + } + + i = 0; + + for (int y = 0; y < imageHight; y++) + { + for (int x = 0; x < imageWidth; x++) + { + acc = 0; + acck = 0; + + for (int j = 0; j < n; j++) + { + int pos = y + j - n / 2; + + if (pos >= 0 && pos < imageHight) + { + acc += helperImage[i + (j - n / 2) * imageWidth] * gausFilterKernel[j]; + acck += gausFilterKernel[j]; + } + } + + image[i] = (unsigned short)(acc / acck); + + i++; + } + } +} + +int getX(imageBuffer combinedXy) +{ + return (combinedXy & 0xFF) - 0x80; +} + +int getY(imageBuffer combinedXy) +{ + return (combinedXy / 0x100) - 0x80; +} + +void sobelFilter(imageBuffer * srcImage, imageBuffer * dstImage) +{ + int i = 0; + + for (int y = 0; y < imageHight; y++) + { + for (int x = 0; x < imageWidth; x++) + { + int dx = 0; + int dy = 0; + + if (x > 0 && x < imageWidth - 1 && y > 0 && y < imageHight - 1) + { + for (int ix = 0; ix < 3; ix++) + { + for (int iy = 0; iy < 3; iy++) + { + int srcVal = srcImage[(x + ix - 1) + (y + iy - 1) * imageWidth]; + + dx += srcVal * sobelFilterKernel[ix][iy]; + dy += srcVal * sobelFilterKernel[iy][ix]; + } + } + + dx /= 0x800; + dy /= 0x800; + + if (dx > 127) dx = 127; + if (dx < -128) dx = -128; + if (dy > 127) dy = 127; + if (dy < -128) dy = -128; + + //dstImage[i] = combineXy(dx,dy); + dstImage[i] = (unsigned short)(dx + 0x80 + (dy + 0x80) * 0x100); + } + else + { + dstImage[i] = 0x8080; + } + + i++; + } + } +} + +int getSlope(imageBuffer value) +{ + int dy = (value / 0x100) - 0x80; + int dx = (value & 0xFF) - 0x80; + + return (dx * dx + dy * dy); +} + +//srcImage must be a result from sobelFilter +void nonMaximumSuppression(imageBuffer * srcImage, imageBuffer * dstImage, int minSlope) +{ + int i = 0; + int slope; + + for (int y = 0; y < imageHight; y++) + { + for (int x = 0; x < imageWidth; x++) + { + + if (x > 0 && x < imageWidth - 1 && y > 0 && y < imageHight - 1) + { + slope = getSlope(srcImage[i]); + + if (slope < minSlope) + { + dstImage[i] = 0x8080; + } + else + { + int count = 0; + + if (getSlope(srcImage[i - 1 - imageWidth]) > slope) count++; + if (getSlope(srcImage[i - 0 - imageWidth]) > slope) count++; + if (getSlope(srcImage[i + 1 - imageWidth]) > slope) count++; + if (getSlope(srcImage[i - 1]) > slope) count++; + if (getSlope(srcImage[i + 1]) > slope) count++; + if (getSlope(srcImage[i - 1 + imageWidth]) > slope) count++; + if (getSlope(srcImage[i - 0 + imageWidth]) > slope) count++; + if (getSlope(srcImage[i + 1 + imageWidth]) > slope) count++; + + if (count > 2) + dstImage[i] = 0x8080; + else + dstImage[i] = srcImage[i]; + } + } + else + { + dstImage[i] = 0x8080; + } + + i++; + } + } +} + + +/*void drawLine(imageBuffer* dstImage, int x0, int y0, int x1, int y1) +{ + int x = x0; + int y = y0; + int dx = x1 - x0; + int dy = y1 - y0; + int err = dx + dy, e2; // error value e_xy + + while (true) + { + dstImage[y * IMAGE_WIDTH + x] += 1;// 64 + cr; + if (x == x1 && y == y1) break; + e2 = 2 * err; + if (e2 > dy) { err += dy; x++; } + if (e2 < dx) { err += dx; y++; } + } +}*/ + +void houghTransformCircles(imageBuffer * srcImage, imageBuffer * dstImage) +{ + int i = 0; + int xslope, yslope; + + for (int y = 0; y < imageHight; y++) + { + for (int x = 0; x < imageWidth; x++) + { + if (srcImage[i] != 0x8080) + { + xslope = getX(srcImage[i]); + yslope = getY(srcImage[i]); + + if (xslope * xslope > yslope * yslope) + { + for (int xi = 0; xi < imageWidth; xi++) + { + int yi = (xi - x) * yslope / xslope + y; + + if (yi > 0 && yi < imageHight) + dstImage[yi * imageWidth + xi]++; + } + } + else + { + for (int yi = 0; yi < imageHight; yi++) + { + int xi = (yi - y) * xslope / yslope + x; + + if (xi > 0 && xi < imageWidth) + dstImage[yi * imageWidth + xi]++; + } + } + } + + i++; + } + } + +} + +void intenerlal_houghTransformLines(imageBuffer * srcImage, imageBuffer * dstImage, int filter) +{ + int i = 0; + const int cx = imageWidth / 2; + const int cy = imageHight / 2; + + for (int y = 0; y < imageHight; y++) + { + for (int x = 0; x < imageWidth; x++) + { + if (srcImage[i] != 0x8080) + { + int xslope = getX(srcImage[i]); + int yslope = getY(srcImage[i]); + int xslope2 = xslope * xslope; + int yslope2 = yslope * yslope; + + if (filter == 0 || (filter == 1 && yslope2 > xslope2) || (filter == 2 && yslope2 < xslope2)) + { + + int inter = ((x - cx) * xslope + (y - cy) * yslope) * 0x100 / (xslope2 + yslope2); + int htx = cx + inter * xslope / 0x100; + int hty = cy + inter * yslope / 0x100; + + if (htx > 0 && htx < imageWidth && hty > 0 && hty < imageHight && dstImage[hty * imageWidth + htx] < 0xFFFF) + dstImage[hty * imageWidth + htx] ++; + + //std::cout << htx << " " << hty << " - " << xslope << " " << yslope << " " << ".\n"; + //printf("%i %i %i %i\n", htx, hty, xslope, yslope); + } + + } + + i++; + } + } +} + +void houghTransformLines(imageBuffer* srcImage, imageBuffer* dstImage) +{ + intenerlal_houghTransformLines(srcImage, dstImage, 0); +} + +void houghTransformVerticalLines(imageBuffer* srcImage, imageBuffer* dstImage) +{ + intenerlal_houghTransformLines(srcImage, dstImage, 2); +} + +void houghTransformHorizontalLines(imageBuffer* srcImage, imageBuffer* dstImage) +{ + intenerlal_houghTransformLines(srcImage, dstImage, 1); +} + +static int usqrt4(int val) { + int a, b; + + a = 256; // starting point is relatively unimportant + + b = val / a; a = (a + b) / 2; + b = val / a; a = (a + b) / 2; + b = val / a; a = (a + b) / 2; + b = val / a; a = (a + b) / 2; + b = val / a; a = (a + b) / 2; + + return a; +} + +void houghTransformMiniscus(imageBuffer * srcImage, imageBuffer * dstImage) +{ + int i = 0; + + for (int y = 0; y < imageHight; y++) + { + for (int x = 0; x < imageWidth; x++) + { + if (srcImage[i] != 0) + { + int xslope = getX(srcImage[i]); + int yslope = getY(srcImage[i]); + + if (xslope != 0) + { + int preCalc = 0x1000 * yslope / xslope; + + + for (int htx = 0; htx < imageWidth; htx++) + { + int dx = htx - x; + //int dy = dx * yslope / xslope; + int dy = dx * preCalc / 0x1000; + + if (dx != 0) + { + int r = usqrt4(dx * dx + dy * dy); + //int r = sqrt(dx * dx + dy * dy); + + int hty = y + dy - r; + + if (hty >= 0 && hty < imageHight) + dstImage[hty * imageWidth + htx] ++; + } + + } + + } + } + + i++; + } + } +} + +void findMaxima(imageBuffer* srcImage, imageBuffer* dstImage, int threshold, int minDistance) +{ + int ws2 = minDistance / 2; + int maxVal; + int maxInd; + + for (int i = 0; i < imageBufferSize; i++) + { + dstImage[i] = srcImage[i]; + } + + for (int y = ws2; y < imageHight; y += ws2) + { + for (int x = ws2; x < imageWidth; x += ws2) + { + maxVal = threshold; + maxInd = -1; + + for (int ix = -ws2; ix < ws2; ix++) + { + for (int iy = -ws2; iy < ws2; iy++) + { + int i = (x + ix) + (y + iy) * imageWidth; + + if (srcImage[i] > maxVal) + { + maxInd = i; + maxVal = srcImage[i]; + } + } + } + + for (int ix = -ws2; ix < ws2; ix++) + { + for (int iy = -ws2; iy < ws2; iy++) + { + int i = (x + ix) + (y + iy) * imageWidth; + if (i != maxInd) + dstImage[i] = 0; + } + } + + + } + } +} + +void bubbleSort(struct pixel_list* array, int length) +{ + int i, j; + struct pixel_list tmp; + + for (i = 1; i < length; i++) + { + for (j = 0; j < length - i; j++) + { + if (array[j].value[4] < array[j + 1].value[4]) + { + tmp = array[j]; + array[j] = array[j + 1]; + array[j + 1] = tmp; + } + } + } +} + +int getPixelList(imageBuffer* primImage, imageBuffer* secImage, struct pixel_list* list, int listLenght) +{ + int i = 0; + int j = 0; + + for (int y = 1; y < imageHight - 1; y++) + { + for (int x = 1; x < imageWidth - 1; x++) + { + i = x + y * imageWidth; + + if (primImage[i] != 0 && j < listLenght) + { + list[j].value[0] = secImage[x + (y - 1) * imageWidth - 1]; + list[j].value[1] = secImage[x + (y - 1) * imageWidth]; + list[j].value[2] = secImage[x + (y - 1) * imageWidth + 1]; + + list[j].value[3] = secImage[i - 1]; + list[j].value[4] = secImage[i]; + list[j].value[5] = secImage[i + 1]; + + list[j].value[6] = secImage[x + (y + 1) * imageWidth - 1]; + list[j].value[7] = secImage[x + (y + 1) * imageWidth]; + list[j].value[8] = secImage[x + (y + 1) * imageWidth + 1]; + + list[j].x = x; + list[j].y = y; + j++; + } + + i++; + } + } + + bubbleSort(list, listLenght); + + return j; +} + +void convertToSlope(imageBuffer* srcImage, imageBuffer* dstImage) +{ + for (int i = 0; i < imageBufferSize; i++) + { + dstImage[i] = (unsigned short)getSlope(srcImage[i]); + } +} + +void binarize(imageBuffer * srcImage, imageBuffer * dstImage, int threshold) +{ + for (int i = 0; i < imageBufferSize; i++) + { + dstImage[i] = (srcImage[i] > threshold) ? 0xFFFF : 0; + } +} + +void clearBufferArea(imageBuffer * dstImage, int startLine, int endLine) +{ + for (int i = 0; i < imageBufferSize; i++) + { + if (i / imageWidth >= startLine && i / imageWidth < endLine) + dstImage[i] = 0; + } +} + +void clearBuffer(imageBuffer* dstImage) +{ + clearBufferArea(dstImage, 0, imageHight); +} diff --git a/src/imageRec.d b/src/imageRec.d new file mode 100644 index 0000000..aba8030 --- /dev/null +++ b/src/imageRec.d @@ -0,0 +1,3 @@ +src/imageRec.o: src/imageRec.c src/imageRec.h + +src/imageRec.h: diff --git a/src/imageRec.h b/src/imageRec.h new file mode 100755 index 0000000..3159a1a --- /dev/null +++ b/src/imageRec.h @@ -0,0 +1,43 @@ + +#define RADIUS_VAL 500 + +typedef unsigned short imageBuffer; +typedef int bool; + +struct pixel_list { + imageBuffer value[9]; + int x; + int y; +}; + +int setImageSize(int width, int hight); + +void normalizeImage(imageBuffer* srcImage, imageBuffer* dstImage); + +void gausFilter(imageBuffer* image, imageBuffer* helperImage); + +void sobelFilter(imageBuffer* srcImage, imageBuffer* dstImage); + +void nonMaximumSuppression(imageBuffer* srcImage, imageBuffer* dstImage, int minSlope); + +void houghTransformCircles(imageBuffer* srcImage, imageBuffer* dstImage); + +void houghTransformLines(imageBuffer* srcImage, imageBuffer* dstImage); + +void houghTransformVerticalLines(imageBuffer* srcImage, imageBuffer* dstImage); + +void houghTransformHorizontalLines(imageBuffer* srcImage, imageBuffer* dstImage); + +void houghTransformMiniscus(imageBuffer* srcImage, imageBuffer* dstImage); + +void findMaxima(imageBuffer* srcImage, imageBuffer* dstImage, int threshold, int minDistance); + +int getPixelList(imageBuffer* primImage, imageBuffer* secImage, struct pixel_list* list, int listLenght); + +void convertToSlope(imageBuffer* srcImage, imageBuffer* dstImage); + +void binarize(imageBuffer* srcImage, imageBuffer* dstImage, int threshold); + +void clearBufferArea(imageBuffer* dstImage, int startLine, int endLine); + +void clearBuffer(imageBuffer* dstImage); \ No newline at end of file diff --git a/src/imageRec.o b/src/imageRec.o new file mode 100644 index 0000000000000000000000000000000000000000..410baaa7dfd799036b2cdc164eb0c89ac275b45f GIT binary patch literal 15428 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 WRwlsp6`|Zf*Nz1`#{u#v-TwgtWH|r; literal 0 HcmV?d00001 diff --git a/src/main.c b/src/main.c new file mode 100755 index 0000000..a00c165 --- /dev/null +++ b/src/main.c @@ -0,0 +1,681 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "imageRec.h" +#include "cmdTcpipClient.h" + +imageBuffer* buffers[3]; +struct pixel_list maxima[32]; + +unsigned char* buffer; +int useTcpIp = 0; +int silent = 0; +int tcpsilent = 0; + +static int xioctl(int fd, int request, void* arg) +{ + int r; + + do r = ioctl(fd, (unsigned long)request, arg); + while (-1 == r && EINTR == errno); + + return r; +} + +int configImageFormat(int fd, struct v4l2_cropcap *cropcap, unsigned int camWidth, unsigned int camHight) +{ + struct v4l2_capability caps = {}; + + if (-1 == xioctl(fd, VIDIOC_QUERYCAP, &caps)) + { + perror("Querying capabilities failed"); + return 1; + } + + if (!silent) printf("Driver caps:\n" + " Driver: \"%s\"\n" + " Card: \"%s\"\n" + " Bus: \"%s\"\n" + " Version: %d.%d\n" + " Capabilities: %08x\n", + caps.driver, caps.card, caps.bus_info, (caps.version >> 16) && 0xff, + (caps.version >> 24) && 0xff, caps.capabilities); + + cropcap->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + if (-1 == xioctl(fd, VIDIOC_CROPCAP, cropcap)) + { + perror("Querying cropping capabilities failed"); + return 1; + } + + int formatIsSupported = 0; + + struct v4l2_fmtdesc fmtdesc = { 0 }; + + fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + char fourcc[5] = { 0 }; + char c, e; + + while (0 == xioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc)) + { + strncpy(fourcc, (char*)& fmtdesc.pixelformat, 4); + + if (fmtdesc.pixelformat == V4L2_PIX_FMT_YUYV) + formatIsSupported = 1; + + c = fmtdesc.flags & 1 ? 'C' : ' '; + e = fmtdesc.flags & 2 ? 'E' : ' '; + if (!silent) printf(" %s: %c%c %s\n", fourcc, c, e, fmtdesc.description); + fmtdesc.index++; + } + + if (!formatIsSupported) + { + perror("Pixel format is not supported\n"); + return 1; + } + + struct v4l2_format fmt = { 0 }; + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + fmt.fmt.pix.width = camWidth; + fmt.fmt.pix.height = camHight; + fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; + fmt.fmt.pix.field = V4L2_FIELD_NONE; + + if (!silent) printf("Requested camera settings:\n" + " Width: %d\n" + " Height: %d\n" + " Pixel format: %s\n", + fmt.fmt.pix.width, + fmt.fmt.pix.height, + fourcc); + + if (-1 == xioctl(fd, VIDIOC_S_FMT, &fmt)) + { + perror("Setting pixel format failed"); + return 1; + } + + strncpy(fourcc, (char*)& fmt.fmt.pix.pixelformat, 4); + + if (!silent) printf("Selected camera settings:\n" + " Width: %d\n" + " Height: %d\n" + " Pixel format: %s\n", + fmt.fmt.pix.width, + fmt.fmt.pix.height, + fourcc); + return 0; +} + +int initMmap(int fd) +{ + struct v4l2_requestbuffers req = { 0 }; + req.count = 1; + req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + req.memory = V4L2_MEMORY_MMAP; + + if (-1 == xioctl(fd, VIDIOC_REQBUFS, &req)) + { + perror("Requesting buffer failed (initMmap)"); + return 1; + } + + struct v4l2_buffer buf = { 0 }; + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = 0; + if (-1 == xioctl(fd, VIDIOC_QUERYBUF, &buf)) + { + perror("Querying buffer failed (initMmap)"); + return 1; + } + + buffer = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset); + + return 0; +} + +int captureImage(int fd, imageBuffer* destBuffer, unsigned int targetBufferSize) +{ + unsigned int buffSize; + + struct v4l2_buffer buf = { 0 }; + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = 0; + if (-1 == xioctl(fd, VIDIOC_QBUF, &buf)) + { + perror("Query buffer failed (captureImage)"); + return 1; + } + + if (-1 == xioctl(fd, VIDIOC_STREAMON, &buf.type)) + { + perror("Query start Capture failed"); + return 1; + } + + fd_set fds; + FD_ZERO(&fds); + FD_SET(fd, &fds); + struct timeval tv = { 0 }; + tv.tv_sec = 2; + int r = select(fd + 1, &fds, NULL, NULL, &tv); + if (-1 == r) + { + perror("Waiting for frame timed out"); + return 1; + } + + if (-1 == xioctl(fd, VIDIOC_DQBUF, &buf)) + { + perror("Retrieving frame failed"); + return 1; + } + + if (buf.bytesused / 2 > targetBufferSize) + buffSize = targetBufferSize; + else + buffSize = buf.bytesused / 2; + + //Extract 8 Bit monocrome Y data from YUYV + for (int i = 0; i < buffSize; i++) + destBuffer[i] = (imageBuffer)buffer[i * 2] * 0x100; + + return 0; +} + +void printOut(char text[]) +{ + int i = 0; + + if (useTcpIp && !tcpsilent) + { + while (text[i] != 0) i++; + sendTcpData((char*)text, i); + } + else + { + if (!silent) printf("%s", text); + } +} + +void printOutChar(char character) +{ + if (useTcpIp) + sendTcpData(&character, 1); + else + printf("%c", character); +} + +void numberToString(int number, int divPos) { + int i = 10000; + int dCount; + int tempVal; + char divVal; + + if (number < 0) + { + printOutChar('-'); + number *= -1; + } + + if (number) + { + dCount = 5 - divPos; + tempVal = number; + while (i) + { + if (number >= i) + { + divVal = (char)(tempVal / i); + printOutChar(divVal + 48); + tempVal -= divVal * i; + } + else if (dCount < 2) + { + printOutChar('0'); + } + + i /= 10; + dCount -= 1; + if (!dCount && i) printOutChar('.'); + } + } + else + { + printOutChar('0'); + } +} + +int write16BitTiff(unsigned short* imageData, unsigned int width, unsigned int height, char* filePath) +{ + FILE* f; + + const unsigned char ofst = 0x86; //134=4+4+2+10*12+4 + + unsigned char iwlo = (unsigned char)(width & 0xFF); + unsigned char iwhi = (unsigned char)(width >> 8); + unsigned char ihlo = (unsigned char)(height & 0xFF); + unsigned char ihhi = (unsigned char)(height >> 8); + + unsigned int imagePixels = width * height; + unsigned int imageBytes = imagePixels * 2; + unsigned char iblo = (unsigned char)(imageBytes & 0xFF); + unsigned char ibhi = (unsigned char)((imageBytes >> 8) & 0xFF); + unsigned char ibvh = (unsigned char)(imageBytes >> 16); + + unsigned char file_header[] = + { + 'I', 'I', 42, 0, // Little endian magic number + 0x08, 0x00, 0x00, 0x00, // IFD header at byte 8 + 0x0A, 0x00, // 10 IFD tags + 0xfe, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //TIFFTAG_SUBFILETYPE = 0 + 0x00, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, iwlo, iwhi, 0x00, 0x00, //TIFFTAG_IMAGEWIDTH = * + 0x01, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, ihlo, ihhi, 0x00, 0x00, //TIFFTAG_IMAGELENGTH = * + 0x02, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, //BITS_PER_SAMPLE = 16 + 0x03, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, //TIFFTAG_COMPRESSION = 1 (Non) + 0x06, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, //TIFFTAG_PHOTOMETRIC = 1 (BlackIsZero) + 0x11, 0x01, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, ofst, 0x00, 0x00, 0x00, //TIFFTAG_STRIPOFFSETS (image data address) + 0x12, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, //TIFFTAG_ORIENTATION = 1 (start top left) + 0x15, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, //TIFFTAG_SAMPLESPERPIXEL = 1 + 0x17, 0x01, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, iblo, ibhi, ibvh, 0x00, //TIFFTAG_STRIPBYTECOUNTS = 1 + 0x00, 0x00, 0x00, 0x00 + }; + + f = fopen(filePath, "wb"); + + if (f > 0) + { + fwrite(file_header, 1, sizeof(file_header), f); + fwrite(imageData, 2, imagePixels, f); + + fclose(f); + } + + return (f > 0); +} + +int main(int argc, char* argv[]) +{ + int exitFlag = 0; + char buff[1]; + int cbuff = 0; + int nbuff = 0; + int itemCount = 0; + int port = 0; + char* deviceName = "/dev/video0"; + char* filePath = "out.tif"; + imageBuffer* tmpib; + const int buffCount = 3; + char* pEnd = 0; + unsigned int buffSize; + unsigned int camWidth = 640; + unsigned int camHeight = 480; + int maxNumb = 32; + int maxMaxNumb = sizeof(maxima) / sizeof(struct pixel_list); + char* commandStr = ""; + int i = 0; + int j; + int fnIncrPos = -1; + int fnIncr = 0; + + while(i < argc) + { + if (*argv[i] == '-') + { + switch (*(argv[i] + 1)) + { + case 'p': + pEnd = 0; + i++; + if (*commandStr) + printf("Option -p is skiped because -c is specified\n"); + else + if (i < argc) port = strtol(argv[i], &pEnd, 10); + break; + + case 'c': + i++; + + if (port) + printf("Option -c is skiped because -p is specified\n"); + else + if (i < argc) commandStr = argv[i]; + break; + + case 'd': + i++; + if (i < argc) + deviceName = argv[i]; + break; + + case 'f': + i++; + if (i < argc) + { + j = 0; + filePath = argv[i]; + while (filePath[j] != 0) + { + if (filePath[j] == '#') fnIncrPos = j; + j++; + } + } + break; + + case 'r': + i++; + if (i < argc) + { + pEnd = 0; + camWidth = (unsigned int)strtol(argv[i], &pEnd, 10); + if (*pEnd != 0 && *(pEnd + 1) != 0) + camHeight = strtol(pEnd + 1, &pEnd, 10); + } + break; + + case 'n': + i++; + if (i < argc) + maxNumb = strtol(argv[i], &pEnd, 10); + if (maxNumb > maxMaxNumb) maxNumb = maxMaxNumb; + break; + + case 's': + silent = 1; + break; + + case '?': + case 'h': + case '-': + printf("Usage: imagerec [-options]\n"); + printf("options:\n"); + printf(" -h show help\n"); + printf(" -c commands ASCII command string\n"); + printf(" -d port TCP/IP-port to listen on\n"); + printf(" -p device capture device name\n"); + printf(" -r whidth*hight image resolution\n"); + printf(" -n pixels max number of pixels for l command\n"); + printf(" -f file file path for w command (# for index)\n"); + printf(" -d return result data only\n"); + printf("\n"); + printf("examples: imagerec -d /dev/video0 -r 640*480 -p 5044\n"); + printf(" imagerec -d /dev/video0 -r 640*480 -c cgnexCngml -s\n"); + printf(" imagerec -d /dev/video0 -r 640*480 -c cgnexCnw -f result.tif\n"); + printf(" imagerec -d /dev/video0 -r 640*480 -c cgnwexsonwrCnw -f result#.tif\n"); + printf("\n"); + printf("single byte ASCII commands:\n"); + printf(" c capture image\n"); + printf(" n normalize image\n"); + printf(" g apply gausian blur\n"); + printf(" e edge detection with sobel filter, must be\n"); + printf(" folowd by 'x', 'o' or a hough transformation\n"); + printf(" x remove non edge pixel, must be folowd by\n"); + printf(" 'o' or a hough transformation\n"); + printf(" o convert directional slope to absolute slope\n"); + printf(" C circle hough transformation\n"); + printf(" L line hough transformation\n"); + printf(" H line hough transformation (horizontal only)\n"); + printf(" V line hough transformation (vertical only)\n"); + printf(" M miniscus hough transformation\n"); + printf(" b binarize\n"); + printf(" m remove non-local-maxima pixels\n"); + printf(" l list brightes pixels (from max. 32 non black pixels)\n"); + printf(" p list brightes pixel clusters (3x3)\n"); + printf(" q close connection\n"); + printf(" s store a copy of the current buffer\n"); + printf(" r recall a copy of the stored buffer\n"); + printf(" w write buffer to disk (TIF format)\n"); + printf(" z set index for output file name to zero\n"); + printf(" d show result data only\n"); + printf(" i show info and result data (default)\n"); + printf("\n"); + printf("example: echo \"cngexCngmlq\" | nc localhost 5044\n"); + return 0; + + default: + printf("Unknown option: -%c\n", *(argv[i] + 1)); + printf("Type imagerec -h for help\n"); + return 0; + } + + } + i++; + } + + if (!silent) + { + if (port > 0) + printf("Start up ImageRecTool, listen on tcp port %i\n", port); + else + printf("Start up ImageRecTool\n", port); + printf("Type imagerec -h for help\n"); + } + + int fd = open((const char*)deviceName, O_RDWR); + if (fd == -1) + { + perror("Opening video device failed"); + return 1; + } + + struct v4l2_cropcap crcap = { 0 }; + + if (configImageFormat(fd, &crcap, camWidth, camHeight)) + return 1; + + buffSize = (unsigned)setImageSize((int)crcap.bounds.width, (int)crcap.bounds.height); + for (int i = 0; i < buffCount; i++) + { + buffers[i] = (imageBuffer*)malloc(buffSize * sizeof(imageBuffer)); + } + + if (initMmap(fd)) + return 1; + + if (port > 0) + { + if (!setupCmdTcpServer(port)) + { + perror("Opening tcp port failed"); + return 1; + } + useTcpIp = 1; + } + + int ret = 1; + + while (!exitFlag) + { + if (useTcpIp) + { + ret = waitForTcpData(buff, 1); + } + else + { + buff[0] = *commandStr; + commandStr++; + } + + if (ret) + { + cbuff = nbuff; + + switch (buff[0]) + { + case 'c': + if (captureImage(fd, buffers[cbuff], buffSize * sizeof(imageBuffer))) + return 1; + printOut("#image captured\n"); + break; + case 'n': + nbuff = !cbuff; + normalizeImage(buffers[cbuff], buffers[nbuff]); //0.2 ms + printOut("#image normalized\n"); + break; + case 'g': + gausFilter(buffers[cbuff], buffers[!cbuff]); // 14 ms + printOut("#gaus filter applied\n"); + break; + case 'e': + nbuff = !cbuff; + sobelFilter(buffers[cbuff], buffers[nbuff]); //14 ms + printOut("#edges detection by sobel filter applied\n"); + break; + case 'x': + nbuff = !cbuff; + nonMaximumSuppression(buffers[cbuff], buffers[nbuff], 128); //9 ms + printOut("#non-edges removed\n"); + break; + case 'M': + nbuff = !cbuff; + clearBuffer(buffers[nbuff]); //1.5 ms + houghTransformMiniscus(buffers[cbuff], buffers[nbuff]); //36 ms with sqrt + printOut("#miniscus hough transformed\n"); + break; + case 'L': + nbuff = !cbuff; + clearBuffer(buffers[nbuff]); //1.5 ms + houghTransformLines(buffers[cbuff], buffers[nbuff]); + printOut("#line hough transformed\n"); + break; + case 'H': + nbuff = !cbuff; + clearBuffer(buffers[nbuff]); //1.5 ms + houghTransformHorizontalLines(buffers[cbuff], buffers[nbuff]); + printOut("#horizontal lines hough transformed\n"); + break; + case 'V': + nbuff = !cbuff; + clearBuffer(buffers[nbuff]); //1.5 ms + houghTransformVerticalLines(buffers[cbuff], buffers[nbuff]); + printOut("#vertical lines hough transformed\n"); + break; + case 'C': + nbuff = !cbuff; + clearBuffer(buffers[nbuff]); //1.5 ms + houghTransformCircles(buffers[cbuff], buffers[nbuff]); + printOut("#circle hough transformed\n"); + break; + case 'm': + nbuff = !cbuff; + findMaxima(buffers[cbuff], buffers[nbuff], 0x10000 / 5, 32); // 0.5 ms + printOut("#non-maxima pixels removed\n"); + break; + case 'b': + binarize(buffers[cbuff], buffers[cbuff], 0x10000 / 2); //0.2 ms + printOut("#image normalized\n"); + break; + case 'o': + nbuff = !cbuff; + convertToSlope(buffers[cbuff], buffers[nbuff]); //0.2 ms + printOut("#converted to slope\n"); + break; + case 'l': + itemCount = getPixelList(buffers[cbuff], buffers[cbuff], maxima, maxNumb); + printOut("#pixel list: (x y value)\n"); + for (int i = 0; i < itemCount; i++) + { + numberToString(maxima[i].x, 0); + printOutChar(' '); + numberToString(maxima[i].y, 0); + printOutChar(' '); + numberToString(maxima[i].value[4], 0); + printOutChar('\n'); + } + if (useTcpIp) sendTcpData("\n", 1); + printOut("#end of list\n"); + break; + case 'p': + itemCount = getPixelList(buffers[cbuff], buffers[!cbuff], maxima, maxNumb); + printOut("#pixel list: (x y value)\n"); + for (int i = 0; i < itemCount; i++) + { + numberToString(maxima[i].x, 0); + printOutChar(' '); + numberToString(maxima[i].y, 0); + for (j = 0; j < 9; j++) + { + printOutChar(' '); + numberToString(maxima[i].value[j], 0); + } + printOutChar('\n'); + } + if (useTcpIp) sendTcpData("\n", 1); + printOut("#end of list\n"); + break; + case 'w': + if (fnIncrPos > -1) filePath[fnIncrPos] = fnIncr + 48; + if (write16BitTiff(buffers[cbuff], crcap.bounds.width, crcap.bounds.height, filePath)) + printOut("#image written\n"); + else + printOut("#error open file\n"); + + fnIncr++; + if (fnIncr > 9) fnIncr = 0; + break; + case 's': + //swap current buffer with storage buffer (buffer 2) + tmpib = buffers[2]; + buffers[2] = buffers[nbuff]; + buffers[nbuff] = tmpib; + + nbuff = 2; + printOut("#image data stored\n"); + break; + case 'r': + nbuff = 2; + printOut("#image data recalled\n"); + break; + case 'q': + nbuff = 2; + printOut("#close socket\n"); + closeTcpConnection(); + break; + case 'Q': + printOut("#quit application\n"); + exitFlag = 1; + break; + case 'z': + fnIncr = 0; + printOut("#reset index to zero\n"); + break; + case 'i': + tcpsilent = 0; + printOut("#show info and results over tcp/ip\n"); + break; + case 'd': + tcpsilent = 1; + printOut("#show only results over tcp/ip\n"); + break; + case 0: + //end of -c command parameter + exitFlag = 1; + break; + default: + if (buff[0] > 32) + printOut("#unknown command\n"); + } + } + } + + if (useTcpIp) + { + closeTcpConnection(); + close(fd); + } + + if (!silent) printf("quit program\n"); + return 0; +} \ No newline at end of file diff --git a/src/main.d b/src/main.d new file mode 100644 index 0000000..b2c0c11 --- /dev/null +++ b/src/main.d @@ -0,0 +1,5 @@ +src/main.o: src/main.c src/imageRec.h src/cmdTcpipClient.h + +src/imageRec.h: + +src/cmdTcpipClient.h: diff --git a/src/main.o b/src/main.o new file mode 100644 index 0000000000000000000000000000000000000000..30effba9ef20457465cd8fdff8e024b7d6cd9f2a GIT binary patch literal 23284 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