---
# System prepended metadata

title: 2023 NCKU 影像處理 HW1

---

# 2023 NCKU 影像處理 HW1
contributed by [tintinjian12999](https://github.com/tintinjian12999)
L76124157 簡瑋廷
[程式碼在這裡](https://github.com/tintinjian12999/digital_image_processing/tree/main)
## Introduction
  為了增加運算時的效能，這裡透過 c++ 呼叫 opencv 做影像處理的函數部份，並編譯成動態連結檔。 再透過 python 呼叫它並建立 GUI 執行。

用以下指令編譯成動態連結檔
```
g++ -shared -fPIC -o main.so main.cpp $(pkg-config --cflags --libs opencv4)
```

並用以下指令執行 python 程式
```
python3 image_processing.py
```

## C++
```cpp
//main.cpp
void average_filter_cpp(const uchar* inputImage, uchar* outputImage, int rows, int cols) {
    Mat inputMat(rows, cols, CV_8UC1, const_cast<uchar*>(inputImage));
    Mat outputMat(rows, cols, CV_8UC1, outputImage);
    blur(inputMat, outputMat,Size(3, 3));
    outputMat.copyTo(cv::Mat(rows, cols, CV_8UC1, outputImage));
}
```
主要是透過 c++ 執行函數的功能並輸出處理後的圖片，整個 c++ 檔打包成 `extern "C"` 的形式。

## python

```python
#image_processing.py
image_processing_lib = ctypes.CDLL('./main.so') # For Linux

image_processing_lib.average_filter_cpp.argtypes = [POINTER(c_ubyte),
                                                     POINTER(c_ubyte),
                                                     c_int,
                                                     c_int]
image_processing_lib.average_filter_cpp.restype = None

image_processing_lib.median_filter_cpp.argtypes = [POINTER(c_ubyte),
                                                    POINTER(c_ubyte),
                                                    c_int,
                                                    c_int]
image_processing_lib.median_filter_cpp.restype = None
```
用來引入 c++ 的動態連接檔並定義函數的傳入傳出形式。

```python
def smooth_filter(self):
        method_set = ['average', 'median', 'fourier']
        if self.image is not None: 
            for i, method in enumerate(['average', 'median', 'fourier']):
                label = Label(self.master, text=f"{method.capitalize()} Filter")
                col_num = 0 if i in [1] else 3
                label.grid(row=min(2, i + 1), column=col_num, columnspan=3)
                self.processed_labels[method] = label
            image_ptr = self.image.ctypes.data_as(POINTER(c_ubyte))
            output_median = np.ones_like(self.image) * 255
            output_median_ptr = output_median.ctypes.data_as(POINTER(c_ubyte))
            output_average = np.ones_like(self.image) * 255
            output_average_ptr = output_average.ctypes.data_as(POINTER(c_ubyte))
            output_fourier = np.ones_like(self.image) * 255
            output_fourier_ptr = output_fourier.ctypes.data_as(POINTER(c_ubyte))
            image_processing_lib.average_filter_cpp(image_ptr, output_average_ptr, self.image.shape[0],
                                                    self.image.shape[1])
            image_processing_lib.median_filter_cpp(image_ptr, output_median_ptr, self.image.shape[0],
                                                    self.image.shape[1])
            image_processing_lib.fourier_filter_cpp(image_ptr, output_fourier_ptr, self.image.shape[0],
                                                    self.image.shape[1])
            self.processed_images['median'] = output_median
            self.processed_images['fourier'] = output_fourier
            self.processed_images['average'] = output_average
            self.show_processed_images(method_set)
```
在下方定義 GUI 的類別中呼叫編譯後的 c++ 函數執行並轉換成 opencv 的資料型態進行圖片輸出。

## 執行結果
### 界面
![圖片](https://hackmd.io/_uploads/BJfTFV6Ha.png)
在按下 open image 並載入圖片後會顯示原始圖像。
![圖片](https://hackmd.io/_uploads/SyZxc4pra.png)

### Smooth filter
按下 Smooth Filter 後會出現以下結果
![圖片](https://hackmd.io/_uploads/BJ5M9VpH6.png)
### Sharp
重新讀取為 Figure_2 並按下 Sharp 會出現以下結果
![2023-12-06 08-03-44 的螢幕擷圖](https://hackmd.io/_uploads/rJf6c4ar6.png)

### Gaussian blur
按下 Gaussian blur 會出現以下結果
![2023-12-06 08-06-13 的螢幕擷圖](https://hackmd.io/_uploads/Hk7boVpB6.png)
### Gaussian lowpass
按下 Gaussian lowpass 會出現以下結果
![2023-12-06 08-06-53 的螢幕擷圖](https://hackmd.io/_uploads/ryyEsV6HT.png)
