\section{Data Size Decision Framework}
\label{sec:design}

This section presents the proposed method that can compress the image into a smaller size compare to jpeg image when we can tolerate some error of data. We use the image captured by FLIR ONE PRO. The temperature in a same object is similar, but an Obvious edge between different objects. Hence, we can separate an image into several regions, and the pixels in a same region has similar value so we can use the average value to represent it and do not cause too much error. However, precisely separate an image into some polygon region is very difficult, and need a lot of computation power. Also, decide the number of region also a problem. Hence, to effectively describe regions we design that every region most be a rectangle, and every region can only separate into 4 regions by cut in half at the middle of horizontal and vertical. The image will start from only contains one region, and 3 regions will be added per round since we cut a region into 4 pieces.

Our method is shown in Figure~\ref{fig:SystemArchitecture}. Data structure initialize only need to do once if the size of image doesn't change. A thermal image will be loaded into our data structure and separate into several regions. Finally, output data will be encoded by Huffman coding, and transmit to database. When users want to use the image, they can get the encoded data from database. 

\begin{figure}[htbp]
	\centering
 	\includegraphics[width=\columnwidth]{figures/SystemArchitecture.pdf}
	\caption{System Architecture}
	\label{fig:SystemArchitecture}
\end{figure} 

\subsection{Region Represent Grammar}

For each frame, we can use a context-free language to represent it.
\begin{center}
\begin{tabular}{rl}
    $S \rightarrow\ $ & $R$ \\
    $R \rightarrow\ $ & $\alpha$\\
    $R \rightarrow\ $ & $\beta RRRR$
\end{tabular}
\end{center}

$R$ means a region of image, and it can either use the average $\alpha$ of the pixels in the region to represent whole region or separate into four regions and left a remainder $\beta$. Dependence on the image size we desired, we can choose the amount of separating regions.  
The context-free grammar start from a region contain whole image. For each $R$ we calculate a score which is based on the data various in the region. After some operation, we can encode the image into a string $\omega$. Figure~\ref{fig:pngImage} shows an example of image which was took by FLIR ONE PRO. One of the possible outcome is Figure~\ref{fig:SeparateImage} if we separate the image 6 times and it will have 19 regions. By this method, we can iteratively separate an image until the number of regions reach our file size requirement.


\begin{figure}[ht]
	\begin{minipage}[b]{0.45\linewidth}
		\centering
		\includegraphics[width=\linewidth]{figures/real.png}
		\caption{PNG image, size = 46KB}
		\label{fig:pngImage}
	\end{minipage}
	\hspace{0.05\linewidth}
	\begin{minipage}[b]{0.45\linewidth}
		\centering
		\includegraphics[width=\linewidth]{figures/separate.png}
		\caption{Region separate by CFG}
		\label{fig:SeparateImage}
	\end{minipage}
\end{figure}

\subsection{Data Structure and Region Selection Algorithm}

To help us choose which region to be separated, we give every region a score, and put them into a heap. For each round, we pick the region with the highest score, separate it into four subregions, calculate the score of subregions, and put them into the heap. We use the sum of square error of pixels in the region $R$ as the score of the region.

\begin{center}
\begin{tabular}{rl}
    $\mu = $ & $E(R)$\\
    $Score = $ & $\sum\limits_{X\in R} (X-\mu)^2$\\
    $= $ & $\sum\limits_{X\in R} X^2 - |R|\mu^2$
\end{tabular}
\end{center}

By the equation shows above, we just need to know the sum of squared and the mean of a region to calculate its score. We use a 4-dimension segment tree to store all possible regions and its scores. Since segment tree is a complete tree, the size of tree is less than 2 times the number if pixels. For each node of segment tree, it records the range on both width and height it covered, sum $\sum\limits_{X\in R} X$, and squared sum $\sum\limits_{X\in R} X^2$ of pixels in the region. By the property of segment tree, tree root start from $0$, and each node $X_i$ has four child $X_{i\times 4+1}$, $X_{i\times 4+2}$, $X_{i\times 4+3}$ and $X_{i\times 4+4}$. Hence, we only need to allocate a large array and recursively process all nodes form root. Algorithm~\ref{code:SegmentTreePreprocess} shows how we generate the tree.

\begin{algorithm*}[h]
	\caption{Segment Tree Preprocess}
	\label{code:SegmentTreePreprocess}
	\begin{algorithmic}[1]
		\State $Tree = Array()$
		\Function{setTreeNode}{$x, left, right, top, bottom$}
			\If {$left = right$ \and $top = bottom$}
				\State $Tree[x].Sum = Image[left][top]$
				\State $Tree[x].SquareSum = Image[left][top]^2$
			\Else
				\State $setTreeNode(4x+1, left, (left+right)/2, top, (top+bottom)/2)$
				\State $setTreeNode(4x+2, (left+right)/2, right, top, (top+bottom)/2)$
				\State $setTreeNode(4x+3, left, (left+right)/2, (top+bottom)/2, bottom)$
				\State $setTreeNode(4x+4, (left+right)/2, right, (top+bottom)/2, bottom)$
				\State $Tree[x].Sum = \sum\limits_{i = 4x+1}^{4x+4} Tree[i].sum $
				\State $Tree[x].SquareSum = \sum\limits_{i = 4x+1}^{4x+4} Tree[i].SquareSum$
			\EndIf
			\State $Tree[x].SquaredError = Tree[x].SquareSum - \frac{Tree[x].Sum^2}{(right-left+1)\times(bottom-top+1)}$ 
		\EndFunction
		\State $setTreeNode(0, 0, Image.Width, 0, Image.Height)$
	\end{algorithmic}
\end{algorithm*}

For region selection, we use a priority queue to retrieve the region of considerate regions with highest score. The priority queue  is made by heap, and start with only root of the segment tree. For each round the priority queue pop the item with highest score and push all its child in to the queue. Algorithm~\ref{code:RegionSelection} shows how we select a region by the priority queue. After the selection finished, we will generate the data string to be sent. The regions in $seperatedRegions$ will be $\beta$ and others in $PriorityQueue$ will be the average value, and then compress the string by Huffman Coding.

\begin{algorithm*}[h]
	\caption{Region Selection}
	\label{code:RegionSelection}
	\begin{algorithmic}[1]
		\State $seperatedRegions = Array()$
		\State $PriorityQueue = Heap()$
		\State $PriorityQueue.Push(Tree[0].SquaredError, 0)$
		\For{\State $i = 0..SeperateRounds$}
			\State $value, x = PriorityQueue.Pop()$
			\State $seperatedRegions.push(x)$
			\State $PriorityQueue.Push(Tree[4x+1].SquaredError, 4x+1)$
			\State $PriorityQueue.Push(Tree[4x+2].SquaredError, 4x+2)$
			\State $PriorityQueue.Push(Tree[4x+3].SquaredError, 4x+3)$
			\State $PriorityQueue.Push(Tree[4x+4].SquaredError, 4x+4)$
		\EndFor
	\end{algorithmic}
\end{algorithm*}

The complexity of our algorithm can be separated into 3 parts. First part is to initialize the segment tree. The size of segment is depends on the size of the image. If the number of pixels is $N$, the height of segment tree is $O(Nlog(N))$, and the number of nodes will be $O(N)$. The time complexity of initialize is $O(N)$. Second part is loading the image. It will need to traverse whole tree from leaf to root. Since segment tree can be stored in an array, it also takes $O(N)$ time to load the image. Third part is to separate regions. For each round, we pop an element from heap and push four elements into heap. If we have separated image $K$ times, the size of heap will be $3K+1$. Time complexity of pop and push will be $O(log(K))$, and do it $5K$ times will be $O(Klog(K))$.
