若圖檔格式不同,輸出圖像變換結果時,就要做一堆前提驗證,例如:
//將 in 圖像的亮度乘上 ratio 後存入 out 中 void adjust_brightness (IplImage* in, IplImage* out, float ratio) { if (in->width != out->width || in->height != out->height) ERROR_MSG_("來源圖像與目的圖像的寬高不相等!"); int x,y, x0; int srcStep = in-> nChannels; int dstStep = out->nChannels; int h = in-> height; uchar* src = (uchar*) in-> imageData; uchar* dst = (uchar*) out->imageData; if (srcStep > dstStep) ERROR_MSG2_("目的圖像的 channel 太小: %d", dstStep); if (srcStep != 1 && srcStep != 3) ERROR_MSG_("來源圖像的 channel 需為 1 或 3"); if (dstStep != 1 && dstStep != 3) ERROR_MSG_("目的圖像的 channel 需為 1 或 3"); if (srcStep == dstStep) { int step = in->nChannels; int W = in->widthStep; int xw = in->width * step; if (step == 1) { //灰階圖 for (y=0; y<h; y++, src+=W, dst+=W) for (x=0; x<xw; x+=step) dst[x] = uchar (src[x] * ratio); } else //24 bits 圖 for (y=0; y<h; y++, src+=W, dst+=W) for (x=0; x<xw; x+=step) { dst[x+0] = uchar (src[x+0] * ratio); dst[x+1] = uchar (src[x+1] * ratio); dst[x+2] = uchar (src[x+2] * ratio); } } else { int srcW = in-> widthStep; int dstW = out->widthStep; int xw = out->width * dstStep; for (y=0; y<h; y++, src+=srcW, dst+=dstW) for (x0=x=0; x<xw; x+=dstStep, ++x0) { dst[x+0] = uchar (src[x0] * ratio); dst[x+1] = uchar (src[x0] * ratio); dst[x+2] = uchar (src[x0] * ratio); } } }設計這些個函式時,有如下幾種規劃:
1. 拿時空換取便利,將所有圖像正規化到同一種格式,例如:32 bits。
2. 寫一個像上面的通用函式,並驗證所有可能的狀況。
3. 引入一個驗證層,將前提檢驗責任交給它:
由於各種可能狀況可事先列出,每種狀況即為驗證層樣板的一個 instance,
對每種影像處理函式選定合適的 instance 即可。
4. 限定影像處理函式只接受他們能處理的影像格式,
對於無法處理的格式,在編譯期強迫程式師事先要做好轉換。
底下是另一個例子,限制 channel 對應只能是
1 -> 1
1 -> 3
3 -> 3
//將 in 的 ROI 拷貝到 out 的 ROI void copy_image_ROI (IplImage* in, IplImage* out) { CvRect srcRect = cvGetImageROI (in); CvRect dstRect = cvGetImageROI (out); if (srcRect.width != dstRect.width || srcRect.height != dstRect.height) ERROR_MSG_("來源圖像與目的圖像的 ROI 寬高不相等!"); int x,y, x0; int srcStep = in ->nChannels; int dstStep = out->nChannels; int srcW = in ->widthStep; int dstW = out->widthStep; int h = srcRect.height; char* src = in ->imageData+ srcRect.y* srcW+ srcRect.x* srcStep; char* dst = out->imageData+ dstRect.y* dstW+ dstRect.x* dstStep; if (srcStep > dstStep) ERROR_MSG2_("目的圖像的 channel 太小: %d", dstStep); if (srcStep != 1 && srcStep != 3) ERROR_MSG_("來源圖像的 channel 需為 1 或 3"); if (dstStep != 1 && dstStep != 3) ERROR_MSG_("目的圖像的 channel 需為 1 或 3"); if (srcStep == dstStep) { int xw = srcRect.width * srcStep; if (srcStep == 1) //灰階圖 for (y=0; y<h; y++, src+=srcW, dst+=dstW) for (x=0; x<xw; ++x) dst[x] = src[x]; else //24 bits 圖 for (y=0; y<h; y++, src+=srcW, dst+=dstW) for (x=0; x<xw; x+=3) { dst[x+0] = src[x+0]; dst[x+1] = src[x+1]; dst[x+2] = src[x+2]; } } else { int xw = dstRect.width * dstStep; for (y=0; y<h; y++, src+=srcW, dst+=dstW) for (x0=x=0; x<xw; x+=3, ++x0) { dst[x+0] = src[x0]; dst[x+1] = src[x0]; dst[x+2] = src[x0]; } } }The Mythical Man-Month:
- 好的設計,既不可單獨偏重功能性,也不可只偏重簡單性。
沒有留言:
張貼留言